From 1315608afc72b73cddccc67f36a48538b53eed48 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 15:03:54 +0400 Subject: [PATCH 001/239] cleanup, typos, warnings --- .../diff/impl/incrementalMerge/MergeBuilder.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java index 10cbbabd69c4..068228032f49 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java @@ -19,12 +19,12 @@ import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.util.ContextLogger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; class MergeBuilder { - //private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeBuilder"); private final ContextLogger LOG; private final int[] myProcessed = new int[]{0, 0, 0}; private final ArrayList myResult = new ArrayList(); @@ -55,7 +55,7 @@ class MergeBuilder { LOG.assertTrue(myPairs[0].getBase() == myPairs[1].getBase()); LOG.assertTrue(myPairs[0].getBase() > myProcessed[1]); addMergeFragment(myPairs[0].processVersion(myProcessed), - proccesBaseChange(myPairs[0]), + processBaseChange(myPairs[0]), myPairs[1].processVersion(myProcessed)); skipProcessed(); } @@ -108,7 +108,7 @@ class MergeBuilder { skipProcessed(); } - private TextRange proccesBaseChange(EqualPair workingPair) { + private TextRange processBaseChange(EqualPair workingPair) { int base = workingPair.getBase(); TextRange change = new TextRange(myProcessed[1], base); int otherBase = myPairs[workingPair.getSide().otherSide().getIndex()].getBase(); @@ -131,7 +131,7 @@ class MergeBuilder { skipProcessed(); } - private void addMergeFragment(TextRange left, TextRange base, TextRange right) { + private void addMergeFragment(@Nullable TextRange left, @Nullable TextRange base, @Nullable TextRange right) { myResult.add(new MergeFragment(new TextRange[]{left, base, right})); } @@ -170,7 +170,7 @@ class MergeBuilder { return myResult; } - private TextRange createRange(int[] starts, int[] ends, int column) { + private static TextRange createRange(int[] starts, int[] ends, int column) { return new TextRange(starts[column], ends[column]); } @@ -183,6 +183,7 @@ class MergeBuilder { myResult.add(new MergeFragment(tailChange)); } + @Nullable private FragmentSide getNotProcessedSide() { EqualPair left = myPairs[0]; EqualPair right = myPairs[1]; @@ -297,7 +298,7 @@ class MergeBuilder { } public String toString() { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); buffer.append("<"); for (int i = 0; i < myRanges.length; i++) { TextRange range = myRanges[i]; From 2cd179d40ee431dcbf0b7e65696bb61046943e0f Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 18:10:18 +0400 Subject: [PATCH 002/239] [merge] refactoring: use structure instead of array indices * MergeFragment: hold TextRanges in named fields instead of operating an array via indices 0, 1, 2. * cleanup, set @NotNull/@Nullable, fix code style. --- .../impl/incrementalMerge/MergeBuilder.java | 118 +++++++++++------- .../diff/impl/incrementalMerge/MergeList.java | 31 +++-- .../incrementalMerge/MergeBuilderTest.java | 2 +- 3 files changed, 91 insertions(+), 60 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java index 068228032f49..a17bc2c3e5e8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java @@ -17,8 +17,8 @@ package com.intellij.openapi.diff.impl.incrementalMerge; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.util.ContextLogger; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -131,8 +131,8 @@ class MergeBuilder { skipProcessed(); } - private void addMergeFragment(@Nullable TextRange left, @Nullable TextRange base, @Nullable TextRange right) { - myResult.add(new MergeFragment(new TextRange[]{left, base, right})); + private void addMergeFragment(@Nullable TextRange left, TextRange base, @Nullable TextRange right) { + myResult.add(new MergeFragment(left, base, right)); } private void skipProcessed() { @@ -149,10 +149,14 @@ class MergeBuilder { } public List finish(int leftLength, int baseLength, int rightLength) { - int[] lengths = new int[]{leftLength, baseLength, rightLength}; - if (isProcessedUpto(lengths)) return myResult; + int[] lengths = new int[]{ leftLength, baseLength, rightLength }; + if (isProcessedUpto(lengths)) { + return myResult; + } int[] afterEnds = new int[3]; - for (int i = 0; i < lengths.length; i++) afterEnds[i] = lengths[i] + 1; + for (int i = 0; i < lengths.length; i++) { + afterEnds[i] = lengths[i] + 1; + } FragmentSide notProcessedSide = getNotProcessedSide(); if (notProcessedSide == null) { addTailChange(lengths); @@ -160,12 +164,10 @@ class MergeBuilder { } myPairs[notProcessedSide.getIndex()].grow(1); FragmentSide processedSide = notProcessedSide.otherSide(); - add(createRange(lengths, afterEnds, 1), - createRange(lengths, afterEnds, processedSide.getMergeIndex()), processedSide); - if (!isProcessedUpto(afterEnds)) - add(createRange(lengths, afterEnds, 1), - createRange(lengths, afterEnds, notProcessedSide.getMergeIndex()), - notProcessedSide); + add(createRange(lengths, afterEnds, 1), createRange(lengths, afterEnds, processedSide.getMergeIndex()), processedSide); + if (!isProcessedUpto(afterEnds)) { + add(createRange(lengths, afterEnds, 1), createRange(lengths, afterEnds, notProcessedSide.getMergeIndex()), notProcessedSide); + } LOG.assertTrue(isProcessedUpto(afterEnds)); return myResult; } @@ -180,7 +182,7 @@ class MergeBuilder { if (i != 1 && myProcessed[i] == lengths[i]) tailChange[i] = null; else tailChange[i] = new TextRange(myProcessed[i], lengths[i]); } - myResult.add(new MergeFragment(tailChange)); + myResult.add(new MergeFragment(tailChange[0], tailChange[1], tailChange[2])); } @Nullable @@ -267,54 +269,86 @@ class MergeBuilder { } } - public static class MergeFragment { - private final TextRange[] myRanges; + public static final class MergeFragment { - public MergeFragment(TextRange[] ranges) { - myRanges = ranges; + @Nullable private final TextRange myLeft; + @NotNull private final TextRange myBase; + @Nullable private final TextRange myRight; + + public MergeFragment(@Nullable TextRange left, @NotNull TextRange base, @Nullable TextRange right) { + myLeft = left; + myBase = base; + myRight = right; } - public TextRange[] getRanges() { - return myRanges; + @Nullable + public TextRange getLeft() { + return myLeft; } - public boolean equals(Object obj) { - if (!(obj instanceof MergeFragment)) return false; - MergeFragment other = (MergeFragment)obj; - for (int i = 0; i < myRanges.length; i++) { - TextRange range = myRanges[i]; - if (!Comparing.equal(range, other.myRanges[i])) return false; - } + @NotNull + public TextRange getBase() { + return myBase; + } + + @Nullable + public TextRange getRight() { + return myRight; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MergeFragment fragment = (MergeFragment)o; + + // suppressing unnecessary check for null, because myBase may occasionally become nullable + //noinspection ConstantConditions + if (myBase != null ? !myBase.equals(fragment.myBase) : fragment.myBase != null) return false; + if (myLeft != null ? !myLeft.equals(fragment.myLeft) : fragment.myLeft != null) return false; + if (myRight != null ? !myRight.equals(fragment.myRight) : fragment.myRight != null) return false; + return true; } + @Override public int hashCode() { - int result = 0; - for (int i = 0; i < myRanges.length; i++) { - TextRange range = myRanges[i]; - result ^= range == null ? i : range.hashCode(); - } + int result = myLeft != null ? myLeft.hashCode() : 0; + // suppressing unnecessary check for null, because myBase may occasionally become nullable + // noinspection ConstantConditions + result = 31 * result + (myBase != null ? myBase.hashCode() : 0); + result = 31 * result + (myRight != null ? myRight.hashCode() : 0); return result; } public String toString() { StringBuilder buffer = new StringBuilder(); buffer.append("<"); - for (int i = 0; i < myRanges.length; i++) { - TextRange range = myRanges[i]; - buffer.append(range != null ? range.toString() : "-----"); - if (i != myRanges.length - 1) buffer.append(", "); - } + buffer.append(range2String(myLeft)).append(", "); + buffer.append(range2String(myBase)).append(", "); + buffer.append(range2String(myRight)); buffer.append(">"); return buffer.toString(); } - public static MergeFragment notConflict(TextRange baseChange, TextRange versionChange, FragmentSide versionSide) { - TextRange[] ranges = new TextRange[3]; - ranges[1] = baseChange; - ranges[versionSide.getMergeIndex()] = versionChange; - ranges[versionSide.otherSide().getMergeIndex()] = null; - return new MergeFragment(ranges); + private static String range2String(@Nullable TextRange left) { + return left != null ? left.toString() : "-----"; + } + + @NotNull + public static MergeFragment notConflict(@NotNull TextRange baseChange, TextRange versionChange, FragmentSide versionSide) { + TextRange left; + TextRange right; + if (versionSide == FragmentSide.SIDE1) { + left = versionChange; + right = null; + } + else { + left = null; + right = versionChange; + } + return new MergeFragment(left, baseChange, right); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index ecc4683eb587..20a1967b67b0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -79,31 +79,30 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { final int fragmentsListSize = fragmentList.size(); for (int i = 0; i < fragmentsListSize; i++) { final MergeBuilder.MergeFragment mergeFragment = fragmentList.get(i); - final TextRange[] ranges = mergeFragment.getRanges(); - logger.assertTrue(ranges[1] != null); - if (ranges[0] == null) { - if (ranges[2] == null) { - if (i == fragmentsListSize - 1 && ranges[1].getEndOffset() == baseText.length()) { + TextRange baseRange = mergeFragment.getBase(); + TextRange leftRange = mergeFragment.getLeft(); + TextRange rightRange = mergeFragment.getRight(); + + if (leftRange == null) { + if (rightRange == null) { + if (i == fragmentsListSize - 1 && baseRange.getEndOffset() == baseText.length()) { // the very end, both local and remote revisions does not contain latest base fragment final int rightTextLength = rightText.length(); final int leftTextLength = leftText.length(); - rightChanges.add(SimpleChange.fromRanges(ranges[1], new TextRange(rightTextLength, rightTextLength), mergeList.myChanges[1])); - leftChanges.add(SimpleChange.fromRanges(ranges[1], new TextRange(leftTextLength, leftTextLength), mergeList.myChanges[0])); + rightChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(rightTextLength, rightTextLength), mergeList.myChanges[1])); + leftChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(leftTextLength, leftTextLength), mergeList.myChanges[0])); } else { LOG.error("Left Text: " + leftText + "\n" + "Right Text: " + rightText + "\nBase Text: " + baseText); } } else { - rightChanges.add(SimpleChange.fromRanges(ranges[1], ranges[2], mergeList.myChanges[1])); + rightChanges.add(SimpleChange.fromRanges(baseRange, rightRange, mergeList.myChanges[1])); } } - else if (ranges[2] == null) { - if (ranges[0] == null) { - LOG.error("Left Text: " + leftText + "\n" + "Right Text: " + rightText + "\nBase Text: " + baseText); - } - leftChanges.add(SimpleChange.fromRanges(ranges[1], ranges[0], mergeList.myChanges[0])); + else if (rightRange == null) { + leftChanges.add(SimpleChange.fromRanges(baseRange, leftRange, mergeList.myChanges[0])); } else { - Change[] changes = MergeConflict.createChanges(ranges[0], ranges[1], ranges[2], mergeList); + Change[] changes = MergeConflict.createChanges(leftRange, baseRange, rightRange, mergeList); leftChanges.add(changes[0]); rightChanges.add(changes[1]); } @@ -113,9 +112,7 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { return mergeList; } - private static List processText(String leftText, - String baseText, - String rightText, + private static List processText(String leftText, String baseText, String rightText, ContextLogger logger) throws FilesTooBigForDiffException { DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, leftText); DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, rightText); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java index 05d325a7d855..01111b25c05c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java @@ -53,7 +53,7 @@ public class MergeBuilderTest extends TestCase { } private MergeBuilder.MergeFragment fragment(TextRange left, TextRange base, TextRange right) { - return new MergeBuilder.MergeFragment(new TextRange[]{left, base, right}); + return new MergeBuilder.MergeFragment(left, base, right); } public void testHeadInsert() { From 62fa9041fa8dafbd6152c4f1bfa00d635668bcb8 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 20:13:18 +0400 Subject: [PATCH 003/239] [merge] cleanup * Remove the deprecated constant. * Logically reorder fields. * Convert for-with-index to Iterator. --- .../diff/impl/incrementalMerge/MergeList.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index 20a1967b67b0..5c15fcec40dc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -45,23 +45,26 @@ import java.util.Iterator; import java.util.List; public class MergeList implements ChangeList.Parent, UserDataHolder { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeList"); - private final Project myProject; - private final ChangeList[] myChanges = new ChangeList[2]; - private final UserDataHolderBase myDataHolder = new UserDataHolderBase(); + public static final FragmentSide BRANCH_SIDE = FragmentSide.SIDE2; public static final FragmentSide BASE_SIDE = FragmentSide.SIDE1; public static final DataKey DATA_KEY = DataKey.create("mergeList"); - @Deprecated public static final String MERGE_LIST = DATA_KEY.getName(); - private MergeList(Project project, Document left, Document base, Document right) { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeList"); + + @NotNull private final Project myProject; + @NotNull private final ChangeList[] myChanges = new ChangeList[2]; + @NotNull private final UserDataHolderBase myDataHolder = new UserDataHolderBase(); + + private MergeList(@NotNull Project project, @NotNull Document left, @NotNull Document base, @NotNull Document right) { myProject = project; myChanges[0] = new ChangeList(base, left, this); myChanges[1] = new ChangeList(base, right, this); } - public static MergeList create(Project project, Document left, Document base, Document right) throws FilesTooBigForDiffException { + public static MergeList create(@NotNull Project project, @NotNull Document left, @NotNull Document base, + @NotNull Document right) throws FilesTooBigForDiffException { MergeList mergeList = new MergeList(project, left, base, right); String leftText = left.getText(); String baseText = base.getText(); @@ -76,16 +79,15 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { ArrayList leftChanges = new ArrayList(); ArrayList rightChanges = new ArrayList(); - final int fragmentsListSize = fragmentList.size(); - for (int i = 0; i < fragmentsListSize; i++) { - final MergeBuilder.MergeFragment mergeFragment = fragmentList.get(i); + for (Iterator fragmentIterator = fragmentList.iterator(); fragmentIterator.hasNext(); ) { + final MergeBuilder.MergeFragment mergeFragment = fragmentIterator.next(); TextRange baseRange = mergeFragment.getBase(); TextRange leftRange = mergeFragment.getLeft(); TextRange rightRange = mergeFragment.getRight(); if (leftRange == null) { if (rightRange == null) { - if (i == fragmentsListSize - 1 && baseRange.getEndOffset() == baseText.length()) { + if (!fragmentIterator.hasNext() && baseRange.getEndOffset() == baseText.length()) { // the very end, both local and remote revisions does not contain latest base fragment final int rightTextLength = rightText.length(); final int leftTextLength = leftText.length(); @@ -229,7 +231,7 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { @Nullable public static MergeList fromDataContext(DataContext dataContext) { - MergeList mergeList = MergeList.DATA_KEY.getData(dataContext); + MergeList mergeList = DATA_KEY.getData(dataContext); if (mergeList != null) return mergeList; MergePanel2 mergePanel = MergePanel2.fromDataContext(dataContext); return mergePanel == null ? null : mergePanel.getMergeList(); @@ -241,6 +243,7 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { } }; + @NotNull public Project getProject() { return myProject; } @@ -253,6 +256,7 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { myDataHolder.putUserData(key, value); } + @Nullable public FragmentSide getSideOf(ChangeList source) { for (int i = 0; i < myChanges.length; i++) { ChangeList changeList = myChanges[i]; From 3630379f2e9833356d1a9130a1ae8c5f55232637 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 20:26:39 +0400 Subject: [PATCH 004/239] [merge] cleanup Remove the Parent interface, because it looks like an overhead. Just pass the Project instance to clients. --- .../impl/incrementalMerge/ChangeList.java | 16 +++++-------- .../diff/impl/incrementalMerge/MergeList.java | 24 +++++++------------ 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java index b44c2225c2f6..ded9f26b3cc1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeList.java @@ -35,15 +35,15 @@ public class ChangeList { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.ChangeList"); private static final Comparator CHANGE_ORDER = new SimpleChange.ChangeOrder(FragmentSide.SIDE1); + private final Project myProject; private final Document[] myDocuments = new Document[2]; - private final Parent myParent; private final ArrayList myListeners = new ArrayList(); private ArrayList myChanges; - public ChangeList(Document base, Document version, Parent parent) { + public ChangeList(Document base, Document version, Project project) { myDocuments[0] = base; myDocuments[1] = version; - myParent = parent; + myProject = project; } public void addListener(Listener listener) { @@ -72,14 +72,14 @@ public class ChangeList { myChanges = new ArrayList(changes); } - public Project getProject() { return myParent.getProject(); } + public Project getProject() { return myProject; } public List getChanges() { return Collections.unmodifiableList(myChanges); } - public static ChangeList build(Document base, Document version, Parent parent) throws FilesTooBigForDiffException { - ChangeList result = new ChangeList(base, version, parent); + public static ChangeList build(Document base, Document version, Project project) throws FilesTooBigForDiffException { + ChangeList result = new ChangeList(base, version, project); ArrayList changes = result.buildChanges(); Collections.sort(changes, CHANGE_ORDER); result.setChanges(changes); @@ -203,10 +203,6 @@ public class ChangeList { } } - public interface Parent { - Project getProject(); - } - public interface Listener { void onChangeRemoved(ChangeList source); } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index 5c15fcec40dc..73ba17f8bb36 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -44,23 +44,26 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -public class MergeList implements ChangeList.Parent, UserDataHolder { +public class MergeList implements UserDataHolder { public static final FragmentSide BRANCH_SIDE = FragmentSide.SIDE2; public static final FragmentSide BASE_SIDE = FragmentSide.SIDE1; public static final DataKey DATA_KEY = DataKey.create("mergeList"); + public static final Condition NOT_CONFLICTS = new Condition() { + public boolean value(Change change) { + return !(change instanceof ConflictChange); + } + }; private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeList"); - @NotNull private final Project myProject; @NotNull private final ChangeList[] myChanges = new ChangeList[2]; @NotNull private final UserDataHolderBase myDataHolder = new UserDataHolderBase(); private MergeList(@NotNull Project project, @NotNull Document left, @NotNull Document base, @NotNull Document right) { - myProject = project; - myChanges[0] = new ChangeList(base, left, this); - myChanges[1] = new ChangeList(base, right, this); + myChanges[0] = new ChangeList(base, left, project); + myChanges[1] = new ChangeList(base, right, project); } public static MergeList create(@NotNull Project project, @NotNull Document left, @NotNull Document base, @@ -237,17 +240,6 @@ public class MergeList implements ChangeList.Parent, UserDataHolder { return mergePanel == null ? null : mergePanel.getMergeList(); } - public static final Condition NOT_CONFLICTS = new Condition() { - public boolean value(Change change) { - return !(change instanceof ConflictChange); - } - }; - - @NotNull - public Project getProject() { - return myProject; - } - public T getUserData(@NotNull Key key) { return myDataHolder.getUserData(key); } From f3efdde810fde56049bb1f45b89b968d8c9ea713 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 21:02:54 +0400 Subject: [PATCH 005/239] [merge] refactor: change array & indices to structure * MergeList.myChanges[] * MergeConflict.myChanges[] * cleanup, code style, javadoc, @NotNull/Nullable --- .../impl/incrementalMerge/ConflictChange.java | 12 ++- .../impl/incrementalMerge/MergeConflict.java | 52 ++++++----- .../diff/impl/incrementalMerge/MergeList.java | 87 ++++++++++--------- 3 files changed, 83 insertions(+), 68 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java index 8fc7f10ccce1..6b6b5ead435f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java @@ -19,7 +19,12 @@ import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.util.TextRange; +/** + * One of two conflicting changes. + * @see MergeConflict + */ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListener { + private Side myOriginalSide; private MergeConflict myConflict; @@ -37,7 +42,7 @@ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListe return isBranch(side) ? myOriginalSide : myConflict; } - private boolean isBranch(FragmentSide side) { + private static boolean isBranch(FragmentSide side) { return MergeList.BRANCH_SIDE == side; } @@ -45,14 +50,15 @@ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListe return myOriginalSide; } - public ChangeType getType() { return ChangeType.CONFLICT; } + public ChangeType getType() { + return ChangeType.CONFLICT; + } public ChangeList getChangeList() { return myConflict.getMergeList().getChanges(myOriginalSide.getFragmentSide()); } public void onRemovedFromList() { - myConflict.onChangeRemoved(myOriginalSide.getFragmentSide(), this); myOriginalSide.getRange().removeListener(this); myConflict = null; myOriginalSide = null; diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java index 85f31b07c8e9..be4062058467 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java @@ -15,22 +15,28 @@ */ package com.intellij.openapi.diff.impl.incrementalMerge; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; +/** + * Represents a merge conflict, i.e. two {@link ConflictChange conflicting changes}, one from left, another from right. + */ class MergeConflict extends ChangeType.ChangeSide implements DiffRangeMarker.RangeInvalidListener { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeConflict"); - private final Change.HighlighterHolder myCommonHighlighterHolder = new Change.HighlighterHolder(); - private final MergeList myMergeList; - private final DiffRangeMarker myCommonRange; - private ConflictChange[] myChanges; - private MergeConflict(TextRange commonRange, MergeList mergeList) { + @NotNull private final MergeList myMergeList; + @NotNull private final DiffRangeMarker myCommonRange; + @NotNull private final ConflictChange myLeftChange; + @NotNull private final ConflictChange myRightChange; + @NotNull private final Change.HighlighterHolder myCommonHighlighterHolder = new Change.HighlighterHolder(); + + MergeConflict(TextRange commonRange, MergeList mergeList, TextRange leftMarker, TextRange rightMarker) { myCommonRange = new DiffRangeMarker((DocumentEx)mergeList.getBaseDocument(),commonRange, this); myMergeList = mergeList; + myLeftChange = new ConflictChange(this, FragmentSide.SIDE1, leftMarker); + myRightChange = new ConflictChange(this, FragmentSide.SIDE2, rightMarker); } public Change.HighlighterHolder getHighlighterHolder() { @@ -41,27 +47,28 @@ class MergeConflict extends ChangeType.ChangeSide implements DiffRangeMarker.Ran return myCommonRange; } - public static Change[] createChanges(TextRange leftMarker, TextRange baseMarker, TextRange rightMarker, MergeList mergeList) { - MergeConflict conflict = new MergeConflict(baseMarker, mergeList); - return conflict.createChanges(leftMarker, rightMarker); + @NotNull + public ConflictChange getLeftChange() { + return myLeftChange; } - private Change[] createChanges(TextRange leftMarker, TextRange rightMarker) { - LOG.assertTrue(myChanges == null); - myChanges = new ConflictChange[]{new ConflictChange(this, FragmentSide.SIDE1, leftMarker), - new ConflictChange(this, FragmentSide.SIDE2, rightMarker)}; - return myChanges; + @NotNull + public ConflictChange getRightChange() { + return myRightChange; } public void conflictRemoved() { - for (ConflictChange change : myChanges) { - change.getOriginalSide().getHighlighterHolder().removeHighlighters(); - } + removeHighlighters(myLeftChange); + removeHighlighters(myRightChange); myCommonHighlighterHolder.removeHighlighters(); - myMergeList.removeChanges(myChanges); + myMergeList.removeChanges(myLeftChange, myRightChange); myCommonRange.removeListener(this); } + private static void removeHighlighters(@NotNull ConflictChange change) { + change.getOriginalSide().getHighlighterHolder().removeHighlighters(); + } + public Document getOriginalDocument(FragmentSide mergeSide) { return myMergeList.getChanges(mergeSide).getDocument(MergeList.BRANCH_SIDE); } @@ -70,12 +77,9 @@ class MergeConflict extends ChangeType.ChangeSide implements DiffRangeMarker.Ran conflictRemoved(); } - public void onChangeRemoved(FragmentSide mergeSide, ConflictChange conflictChange) { - LOG.assertTrue(myChanges[mergeSide.getIndex()] == conflictChange); - myChanges[mergeSide.getIndex()] = null; - } - + @NotNull public MergeList getMergeList() { return myMergeList; } + } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index 73ba17f8bb36..fcea6262275b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -58,12 +58,13 @@ public class MergeList implements UserDataHolder { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.MergeList"); - @NotNull private final ChangeList[] myChanges = new ChangeList[2]; @NotNull private final UserDataHolderBase myDataHolder = new UserDataHolderBase(); + @NotNull private final ChangeList myBaseToLeftChangeList; + @NotNull private final ChangeList myBaseToRightChangeList; private MergeList(@NotNull Project project, @NotNull Document left, @NotNull Document base, @NotNull Document right) { - myChanges[0] = new ChangeList(base, left, project); - myChanges[1] = new ChangeList(base, right, project); + myBaseToLeftChangeList = new ChangeList(base, left, project); + myBaseToRightChangeList = new ChangeList(base, right, project); } public static MergeList create(@NotNull Project project, @NotNull Document left, @NotNull Document base, @@ -94,26 +95,26 @@ public class MergeList implements UserDataHolder { // the very end, both local and remote revisions does not contain latest base fragment final int rightTextLength = rightText.length(); final int leftTextLength = leftText.length(); - rightChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(rightTextLength, rightTextLength), mergeList.myChanges[1])); - leftChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(leftTextLength, leftTextLength), mergeList.myChanges[0])); + rightChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(rightTextLength, rightTextLength), mergeList.myBaseToRightChangeList)); + leftChanges.add(SimpleChange.fromRanges(baseRange, new TextRange(leftTextLength, leftTextLength), mergeList.myBaseToLeftChangeList)); } else { LOG.error("Left Text: " + leftText + "\n" + "Right Text: " + rightText + "\nBase Text: " + baseText); } } else { - rightChanges.add(SimpleChange.fromRanges(baseRange, rightRange, mergeList.myChanges[1])); + rightChanges.add(SimpleChange.fromRanges(baseRange, rightRange, mergeList.myBaseToRightChangeList)); } } else if (rightRange == null) { - leftChanges.add(SimpleChange.fromRanges(baseRange, leftRange, mergeList.myChanges[0])); + leftChanges.add(SimpleChange.fromRanges(baseRange, leftRange, mergeList.myBaseToLeftChangeList)); } else { - Change[] changes = MergeConflict.createChanges(leftRange, baseRange, rightRange, mergeList); - leftChanges.add(changes[0]); - rightChanges.add(changes[1]); + MergeConflict conflict = new MergeConflict(baseRange, mergeList, leftRange, rightRange); + leftChanges.add(conflict.getLeftChange()); + rightChanges.add(conflict.getRightChange()); } } - mergeList.myChanges[0].setChanges(leftChanges); - mergeList.myChanges[1].setChanges(rightChanges); + mergeList.myBaseToLeftChangeList.setChanges(leftChanges); + mergeList.myBaseToRightChangeList.setChanges(rightChanges); return mergeList; } @@ -168,31 +169,29 @@ public class MergeList implements UserDataHolder { } public void setMarkups(Editor left, Editor base, Editor right) { - myChanges[0].setMarkup(base, left); - myChanges[1].setMarkup(base, right); + myBaseToLeftChangeList.setMarkup(base, left); + myBaseToRightChangeList.setMarkup(base, right); addActions(FragmentSide.SIDE1); addActions(FragmentSide.SIDE2); } public Iterator getAllChanges() { - return SequenceIterator.create(myChanges[0].getChanges().iterator(), - FilteringIterator.create(myChanges[1].getChanges().iterator(), NOT_CONFLICTS)); + return SequenceIterator.create(myBaseToLeftChangeList.getChanges().iterator(), + FilteringIterator.create(myBaseToRightChangeList.getChanges().iterator(), NOT_CONFLICTS)); } public void addListener(ChangeList.Listener listener) { - for (ChangeList changeList : myChanges) { - changeList.addListener(listener); - } + myBaseToLeftChangeList.addListener(listener); + myBaseToRightChangeList.addListener(listener); } public void removeListener(ChangeList.Listener listener) { - for (ChangeList changeList : myChanges) { - changeList.removeListener(listener); - } + myBaseToLeftChangeList.removeListener(listener); + myBaseToRightChangeList.removeListener(listener); } private void addActions(final FragmentSide side) { - ChangeList changeList = myChanges[side.getIndex()]; + ChangeList changeList = getChanges(side); final FragmentSide originalSide = BRANCH_SIDE; for (int i = 0; i < changeList.getCount(); i++) { final Change change = changeList.getChange(i); @@ -215,20 +214,24 @@ public class MergeList implements UserDataHolder { Change.apply(change, BRANCH_SIDE); } - public ChangeList getChanges(final FragmentSide changesSide) { - return myChanges[changesSide.getIndex()]; - } - - public void removeChanges(Change[] changes) { - for (int i = 0; i < changes.length; i++) { - Change change = changes[i]; - myChanges[i].remove(change); + @NotNull + public ChangeList getChanges(@NotNull final FragmentSide changesSide) { + if (changesSide == FragmentSide.SIDE1) { + return myBaseToLeftChangeList; + } + else { + return myBaseToRightChangeList; } } + public void removeChanges(@NotNull Change leftChange, @NotNull Change rightChange) { + myBaseToLeftChangeList.remove(leftChange); + myBaseToRightChangeList.remove(rightChange); + } + public Document getBaseDocument() { - Document document = myChanges[0].getDocument(BASE_SIDE); - LOG.assertTrue(document == myChanges[1].getDocument(BASE_SIDE)); + Document document = myBaseToLeftChangeList.getDocument(BASE_SIDE); + LOG.assertTrue(document == myBaseToRightChangeList.getDocument(BASE_SIDE)); return document; } @@ -248,17 +251,19 @@ public class MergeList implements UserDataHolder { myDataHolder.putUserData(key, value); } - @Nullable - public FragmentSide getSideOf(ChangeList source) { - for (int i = 0; i < myChanges.length; i++) { - ChangeList changeList = myChanges[i]; - if (changeList == source) return FragmentSide.fromIndex(i); + @NotNull + public FragmentSide getSideOf(@NotNull ChangeList source) { + if (myBaseToLeftChangeList == source) { + return FragmentSide.SIDE1; + } + else { + return FragmentSide.SIDE2; } - return null; } public void updateMarkup() { - myChanges[0].updateMarkup(); - myChanges[1].updateMarkup(); + myBaseToLeftChangeList.updateMarkup(); + myBaseToRightChangeList.updateMarkup(); } + } From f571391945f21b53f0b2b6e4a82b8c93e1081635 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 21:18:10 +0400 Subject: [PATCH 006/239] Extract MergeFragment to a separate class. It is used in several places and is rather big. Added some javadocs. --- .../impl/incrementalMerge/MergeBuilder.java | 84 ------------- .../impl/incrementalMerge/MergeFragment.java | 114 ++++++++++++++++++ .../diff/impl/incrementalMerge/MergeList.java | 8 +- .../incrementalMerge/MergeBuilderTest.java | 14 +-- 4 files changed, 125 insertions(+), 95 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeFragment.java diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java index a17bc2c3e5e8..a0b526cff493 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilder.java @@ -18,7 +18,6 @@ package com.intellij.openapi.diff.impl.incrementalMerge; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; import com.intellij.openapi.diff.impl.util.ContextLogger; import com.intellij.openapi.util.TextRange; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -268,87 +267,4 @@ class MergeBuilder { myLength += delta; } } - - public static final class MergeFragment { - - @Nullable private final TextRange myLeft; - @NotNull private final TextRange myBase; - @Nullable private final TextRange myRight; - - public MergeFragment(@Nullable TextRange left, @NotNull TextRange base, @Nullable TextRange right) { - myLeft = left; - myBase = base; - myRight = right; - } - - @Nullable - public TextRange getLeft() { - return myLeft; - } - - @NotNull - public TextRange getBase() { - return myBase; - } - - @Nullable - public TextRange getRight() { - return myRight; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MergeFragment fragment = (MergeFragment)o; - - // suppressing unnecessary check for null, because myBase may occasionally become nullable - //noinspection ConstantConditions - if (myBase != null ? !myBase.equals(fragment.myBase) : fragment.myBase != null) return false; - if (myLeft != null ? !myLeft.equals(fragment.myLeft) : fragment.myLeft != null) return false; - if (myRight != null ? !myRight.equals(fragment.myRight) : fragment.myRight != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = myLeft != null ? myLeft.hashCode() : 0; - // suppressing unnecessary check for null, because myBase may occasionally become nullable - // noinspection ConstantConditions - result = 31 * result + (myBase != null ? myBase.hashCode() : 0); - result = 31 * result + (myRight != null ? myRight.hashCode() : 0); - return result; - } - - public String toString() { - StringBuilder buffer = new StringBuilder(); - buffer.append("<"); - buffer.append(range2String(myLeft)).append(", "); - buffer.append(range2String(myBase)).append(", "); - buffer.append(range2String(myRight)); - buffer.append(">"); - return buffer.toString(); - } - - private static String range2String(@Nullable TextRange left) { - return left != null ? left.toString() : "-----"; - } - - @NotNull - public static MergeFragment notConflict(@NotNull TextRange baseChange, TextRange versionChange, FragmentSide versionSide) { - TextRange left; - TextRange right; - if (versionSide == FragmentSide.SIDE1) { - left = versionChange; - right = null; - } - else { - left = null; - right = versionChange; - } - return new MergeFragment(left, baseChange, right); - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeFragment.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeFragment.java new file mode 100644 index 000000000000..91096b5d4097 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeFragment.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2012 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.diff.impl.incrementalMerge; + +import com.intellij.openapi.diff.impl.highlighting.FragmentSide; +import com.intellij.openapi.util.TextRange; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Represents one fragment in the 3-way merge, i.e. an insertion, a deletion, a modification or a conflict. + * Holds information about the {@link TextRange TextRanges} of changed fragments.
+ * One and only one left or right fragment is null for all cases, except for the conflict, when both are not null. + */ +final class MergeFragment { + + @Nullable private final TextRange myLeft; + @NotNull private final TextRange myBase; + @Nullable private final TextRange myRight; + + MergeFragment(@Nullable TextRange left, @NotNull TextRange base, @Nullable TextRange right) { + myLeft = left; + myBase = base; + myRight = right; + } + + /** + * Creates a non-conflicting MergeFragment, given one of TextRanges and the FragmentSide to identify which range is it: right or left. + */ + @NotNull + static MergeFragment notConflict(@NotNull TextRange baseChange, @NotNull TextRange versionChange, @NotNull FragmentSide versionSide) { + TextRange left; + TextRange right; + if (versionSide == FragmentSide.SIDE1) { + left = versionChange; + right = null; + } + else { + left = null; + right = versionChange; + } + return new MergeFragment(left, baseChange, right); + } + + @Nullable + TextRange getLeft() { + return myLeft; + } + + @NotNull + TextRange getBase() { + return myBase; + } + + @Nullable + TextRange getRight() { + return myRight; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MergeFragment fragment = (MergeFragment)o; + + // suppressing unnecessary check for null, because myBase may occasionally become nullable + //noinspection ConstantConditions + if (myBase != null ? !myBase.equals(fragment.myBase) : fragment.myBase != null) return false; + if (myLeft != null ? !myLeft.equals(fragment.myLeft) : fragment.myLeft != null) return false; + if (myRight != null ? !myRight.equals(fragment.myRight) : fragment.myRight != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myLeft != null ? myLeft.hashCode() : 0; + // suppressing unnecessary check for null, because myBase may occasionally become nullable + // noinspection ConstantConditions + result = 31 * result + (myBase != null ? myBase.hashCode() : 0); + result = 31 * result + (myRight != null ? myRight.hashCode() : 0); + return result; + } + + public String toString() { + StringBuilder buffer = new StringBuilder(); + buffer.append("<"); + buffer.append(range2String(myLeft)).append(", "); + buffer.append(range2String(myBase)).append(", "); + buffer.append(range2String(myRight)); + buffer.append(">"); + return buffer.toString(); + } + + @NotNull + private static String range2String(@Nullable TextRange left) { + return left != null ? left.toString() : "-----"; + } + +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java index fcea6262275b..95c7fd938aa7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeList.java @@ -79,12 +79,12 @@ public class MergeList implements UserDataHolder { "\nRight\n", rightText }; ContextLogger logger = new ContextLogger(LOG, new ContextLogger.SimpleContext(data)); - List fragmentList = processText(leftText, baseText, rightText, logger); + List fragmentList = processText(leftText, baseText, rightText, logger); ArrayList leftChanges = new ArrayList(); ArrayList rightChanges = new ArrayList(); - for (Iterator fragmentIterator = fragmentList.iterator(); fragmentIterator.hasNext(); ) { - final MergeBuilder.MergeFragment mergeFragment = fragmentIterator.next(); + for (Iterator fragmentIterator = fragmentList.iterator(); fragmentIterator.hasNext(); ) { + final MergeFragment mergeFragment = fragmentIterator.next(); TextRange baseRange = mergeFragment.getBase(); TextRange leftRange = mergeFragment.getLeft(); TextRange rightRange = mergeFragment.getRight(); @@ -118,7 +118,7 @@ public class MergeList implements UserDataHolder { return mergeList; } - private static List processText(String leftText, String baseText, String rightText, + private static List processText(String leftText, String baseText, String rightText, ContextLogger logger) throws FilesTooBigForDiffException { DiffFragment[] leftFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, leftText); DiffFragment[] rightFragments = DiffPolicy.DEFAULT_LINES.buildFragments(baseText, rightText); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java index 01111b25c05c..898f4b8705ba 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/diff/impl/incrementalMerge/MergeBuilderTest.java @@ -46,14 +46,14 @@ public class MergeBuilderTest extends TestCase { TextRange version = new TextRange(0, 1); addLeft(base, version); addRight(base, version); - CHECK.compareAll(new MergeBuilder.MergeFragment[]{ + CHECK.compareAll(new MergeFragment[]{ fragment(new TextRange(0, 0), new TextRange(0, 1), new TextRange(0, 0)), fragment(new TextRange(1, 2), new TextRange(2, 2), new TextRange(1, 2)) }, finish(2, 2, 2)); } - private MergeBuilder.MergeFragment fragment(TextRange left, TextRange base, TextRange right) { - return new MergeBuilder.MergeFragment(left, base, right); + private MergeFragment fragment(TextRange left, TextRange base, TextRange right) { + return new MergeFragment(left, base, right); } public void testHeadInsert() { @@ -73,7 +73,7 @@ public class MergeBuilderTest extends TestCase { public void testNotAllignedConflict() { addLeft(new TextRange(1, 3), new TextRange(0, 2)); addRight(new TextRange(2, 4), new TextRange(1, 3)); - CHECK.compareAll(new MergeBuilder.MergeFragment[]{ + CHECK.compareAll(new MergeFragment[]{ fragment(new TextRange(0, 1), new TextRange(0, 2), new TextRange(0, 1)), fragment(new TextRange(2, 3), new TextRange(3, 4), null) }, finish(3, 4, 3)); @@ -86,7 +86,7 @@ public class MergeBuilderTest extends TestCase { addRight(new TextRange(4, 5), new TextRange(3, 4)); addRight(new TextRange(6, 7), new TextRange(5, 6)); addLeft(new TextRange(9, 10), new TextRange(9, 10)); - CHECK.compareAll(new MergeBuilder.MergeFragment[]{ + CHECK.compareAll(new MergeFragment[]{ fragment(new TextRange(0, 1), new TextRange(0, 1), TextRange.EMPTY_RANGE), fragment(null, new TextRange(2, 3), new TextRange(1, 1)), fragment(null, new TextRange(4, 4), new TextRange(2, 3)), @@ -100,7 +100,7 @@ public class MergeBuilderTest extends TestCase { addRight(new TextRange(0, 2), new TextRange(0, 2)); addLeft(new TextRange(3, 5), new TextRange(1, 3)); addRight(new TextRange(4, 5), new TextRange(2, 3)); - CHECK.compareAll(new MergeBuilder.MergeFragment[]{ + CHECK.compareAll(new MergeFragment[]{ fragment(new TextRange(1, 2), new TextRange(1, 4), new TextRange(1, 2)) }, finish(3, 5, 3)); } @@ -113,7 +113,7 @@ public class MergeBuilderTest extends TestCase { myMergeBuilder.add(base, left, FragmentSide.SIDE1); } - private List finish(int left, int base, int right) { + private List finish(int left, int base, int right) { return myMergeBuilder.finish(left, base, right); } From 741bcb69549fbed8234b5b2a9d77a55df4e2db12 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 18 May 2012 21:37:08 +0400 Subject: [PATCH 007/239] [merge] refactoring: make FragmentSide to be enum * Make some DRY. * Use IllegalArgumentException to a not-public InvalidParameterException --- .../openapi/diff/impl/DiffPanelImpl.java | 2 +- .../diff/impl/fragments/InlineFragment.java | 2 +- .../diff/impl/fragments/LineFragment.java | 3 +- .../diff/impl/highlighting/FragmentSide.java | 130 ++++++++++-------- 4 files changed, 73 insertions(+), 64 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index 5853849359ad..88aaf6e0af8f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -482,7 +482,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid return myLeftSide; } if (side == FragmentSide.SIDE2) return myRightSide; - throw new InvalidParameterException(String.valueOf(side)); + throw new IllegalArgumentException(String.valueOf(side)); } public LineBlocks getLineBlocks() { return myLineBlocks; } diff --git a/platform/util/src/com/intellij/openapi/diff/impl/fragments/InlineFragment.java b/platform/util/src/com/intellij/openapi/diff/impl/fragments/InlineFragment.java index 5e8116586293..8b06e9847b55 100644 --- a/platform/util/src/com/intellij/openapi/diff/impl/fragments/InlineFragment.java +++ b/platform/util/src/com/intellij/openapi/diff/impl/fragments/InlineFragment.java @@ -42,7 +42,7 @@ public class InlineFragment implements Fragment { public TextRange getRange(FragmentSide side) { if (side == FragmentSide.SIDE1) return myRange1; if (side == FragmentSide.SIDE2) return myRange2; - throw new InvalidParameterException(String.valueOf(side)); + throw new IllegalArgumentException(String.valueOf(side)); } public Fragment shift(TextRange range1, TextRange range2, int startingLine1, int startingLine2) { diff --git a/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java b/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java index e56f13277c4b..4aeb74fb3726 100644 --- a/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java +++ b/platform/util/src/com/intellij/openapi/diff/impl/fragments/LineFragment.java @@ -21,7 +21,6 @@ import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; -import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Iterator; @@ -55,7 +54,7 @@ public class LineFragment extends LineBlock implements Fragment { public TextRange getRange(FragmentSide side) { if (side == FragmentSide.SIDE1) return myRange1; if (side == FragmentSide.SIDE2) return myRange2; - throw new InvalidParameterException(String.valueOf(side)); + throw new IllegalArgumentException(String.valueOf(side)); } public Fragment shift(TextRange range1, TextRange range2, int startingLine1, int startingLine2) { diff --git a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java index 8119a53df8ef..2a9a4fed5d2a 100644 --- a/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java +++ b/platform/util/src/com/intellij/openapi/diff/impl/highlighting/FragmentSide.java @@ -17,84 +17,94 @@ package com.intellij.openapi.diff.impl.highlighting; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.ex.DiffFragment; +import org.jetbrains.annotations.NotNull; -import java.security.InvalidParameterException; +public enum FragmentSide { + + SIDE1(0, 0) { + @Override + public String getText(DiffFragment fragment) { + return fragment.getText1(); + } + + @Override + protected DiffFragment createDiffFragment(String text, String otherText) { + return new DiffFragment(text, otherText); + } + + @Override + public FragmentSide otherSide() { + return SIDE2; + } + }, + + SIDE2(1, 2) { + @Override + public String getText(DiffFragment fragment) { + return fragment.getText2(); + } + + @Override + protected DiffFragment createDiffFragment(String text, String otherText) { + return new DiffFragment(otherText, text); + } + + @Override + public FragmentSide otherSide() { + return SIDE1; + } + }; + + private static final Logger LOG = Logger.getInstance(FragmentSide.class); + + private final int myIndex; + private final int myMergeIndex; + + FragmentSide(int index, int mergeIndex) { + myIndex = index; + myMergeIndex = mergeIndex; + } + + public DiffFragment createFragment(String text, String otherText, boolean modified) { + DiffFragment fragment = createDiffFragment(text, otherText); + if (!fragment.isOneSide()) fragment.setModified(modified); + return fragment; + } -public abstract class FragmentSide { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.highlighting.FragmentSide"); public abstract String getText(DiffFragment fragment); - public abstract DiffFragment createFragment(String text, String otherText, boolean modified); public abstract FragmentSide otherSide(); - public abstract int getIndex(); - public abstract int getMergeIndex(); + protected abstract DiffFragment createDiffFragment(String text, String otherText); + + public int getIndex() { + return myIndex; + } + + public int getMergeIndex() { + return myMergeIndex; + } public String getOtherText(DiffFragment fragment) { return otherSide().getText(fragment); } - public InvalidParameterException invalidException() { - return new InvalidParameterException(String.valueOf(this)); + public IllegalArgumentException invalidException() { + return new IllegalArgumentException(String.valueOf(this)); } - public static final FragmentSide SIDE1 = new FragmentSide() { - public String getText(DiffFragment fragment) { - return fragment.getText1(); - } - - public DiffFragment createFragment(String text, String otherText, boolean modified) { - DiffFragment fragment = new DiffFragment(text, otherText); - if (!fragment.isOneSide()) fragment.setModified(modified); - return fragment; - } - - public FragmentSide otherSide() { - return SIDE2; - } - - public int getIndex() { - return 0; - } - - public int getMergeIndex() { - return 0; - } - }; - - public static final FragmentSide SIDE2 = new FragmentSide() { - public String getText(DiffFragment fragment) { - return fragment.getText2(); - } - - public DiffFragment createFragment(String text, String otherText, boolean modified) { - DiffFragment fragment = new DiffFragment(otherText, text); - if (!fragment.isOneSide()) fragment.setModified(modified); - return fragment; - } - - public FragmentSide otherSide() { - return SIDE1; - } - - public int getIndex() { - return 1; - } - - public int getMergeIndex() { - return 2; - } - }; - public static FragmentSide chooseSide(DiffFragment oneSide) { LOG.assertTrue(oneSide.isOneSide()); LOG.assertTrue(oneSide.getText1() != oneSide.getText2()); return oneSide.getText1() == null ? SIDE2 : SIDE1; } + @NotNull public static FragmentSide fromIndex(int index) { - switch (index) { - case 0: return SIDE1; - case 1: return SIDE2; - default: throw new InvalidParameterException(String.valueOf(index)); + for (FragmentSide side : FragmentSide.values()) { + if (side.getIndex() == index) { + return side; + } } + throw new IllegalArgumentException(String.valueOf(index)); } + } From 714fd989fb8f23bc769e1ac6771406538dc50330 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 28 May 2012 16:08:47 +0400 Subject: [PATCH 008/239] [merge] refactoring: move inner classes outside, move some methods, cleanup, code style * Move Change.HighlighterHolder and Change.Side inner classes to outside since they are used a lot from the ouside of the Change class. * Move ChangeType.apply() to Change, because it is nothing to do with the ChangeType: it is the Change which is being applied. * Add some javadocs. * Cleanup. --- .../diff/impl/incrementalMerge/Change.java | 173 +++++------------- .../ChangeHighlighterHolder.java | 140 ++++++++++++++ .../impl/incrementalMerge/ChangeSide.java | 52 ++++++ .../impl/incrementalMerge/ChangeType.java | 75 ++------ .../impl/incrementalMerge/ConflictChange.java | 8 +- .../impl/incrementalMerge/MergeConflict.java | 6 +- .../impl/incrementalMerge/SimpleChange.java | 12 +- 7 files changed, 261 insertions(+), 205 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeSide.java diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java index 553b31a4e6f2..30dab2e70de0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/Change.java @@ -15,45 +15,70 @@ */ package com.intellij.openapi.diff.impl.incrementalMerge; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffBundle; import com.intellij.openapi.diff.impl.highlighting.FragmentSide; -import com.intellij.openapi.diff.impl.util.GutterActionRenderer; -import com.intellij.openapi.diff.impl.util.TextDiffType; +import com.intellij.openapi.diff.impl.util.DocumentUtil; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.editor.markup.HighlighterTargetArea; -import com.intellij.openapi.editor.markup.MarkupModel; -import com.intellij.openapi.editor.markup.RangeHighlighter; -import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.Comparator; +/** + * Represents a change in diff or merge view. + * A change has two {@link com.intellij.openapi.diff.impl.incrementalMerge.Change.SimpleChangeSide sides} (left and right), each of them representing the text which has been changed and the original text + * shown in the diff/merge. + * Change can be applied, then its sides would be equal. + */ public abstract class Change { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.Change"); + public abstract ChangeSide getChangeSide(FragmentSide side); + + public abstract ChangeType getType(); + + public abstract ChangeList getChangeList(); + + protected abstract void removeFromList(); + + public abstract void onRemovedFromList(); + + public abstract boolean isValid(); + private void apply(@NotNull FragmentSide original) { FragmentSide targetSide = original.otherSide(); RangeMarker originalRangeMarker = getRangeMarker(original); RangeMarker rangeMarker = getRangeMarker(targetSide); if (originalRangeMarker != null && rangeMarker != null) { - ChangeType.apply(getProject(), originalRangeMarker, rangeMarker); + apply(getProject(), originalRangeMarker, rangeMarker); if (isValid()) { removeFromList(); } } } - protected abstract void removeFromList(); + private static void apply(@NotNull Project project, @NotNull RangeMarker original, @NotNull RangeMarker target) { + Document document = target.getDocument(); + if (!ReadonlyStatusHandler.ensureDocumentWritable(project, document)) return; + if (DocumentUtil.isEmpty(original)) { + int offset = target.getStartOffset(); + document.deleteString(offset, target.getEndOffset()); + } + String text = DocumentUtil.getText(original); + int startOffset = target.getStartOffset(); + if (DocumentUtil.isEmpty(target)) { + document.insertString(startOffset, text); + } else { + document.replaceString(startOffset, target.getEndOffset(), text); + } + } public void addMarkup(Editor[] editors) { LOG.assertTrue(editors.length == 2); @@ -71,26 +96,16 @@ public abstract class Change { private Project getProject() { return getChangeList().getProject(); } - public abstract ChangeType.ChangeSide getChangeSide(FragmentSide side); - - public abstract ChangeType getType(); - - public abstract ChangeList getChangeList(); - - private HighlighterHolder getHighlighterHolder(FragmentSide side) { + private ChangeHighlighterHolder getHighlighterHolder(FragmentSide side) { return getChangeSide(side).getHighlighterHolder(); } private RangeMarker getRangeMarker(FragmentSide side) { - ChangeType.ChangeSide changeSide = getChangeSide(side); + ChangeSide changeSide = getChangeSide(side); LOG.assertTrue(changeSide != null); return changeSide.getRange(); } - public abstract void onRemovedFromList(); - - public abstract boolean isValid(); - public static void apply(final Change change, final FragmentSide fromSide) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { @@ -134,116 +149,12 @@ public abstract class Change { } } - protected static class HighlighterHolder implements ChangeType.MarkupHolder { - private Editor myEditor; - private final ArrayList myHighlighters = new ArrayList(3); - private RangeHighlighter myMainHighlighter = null; - private AnAction[] myActions; - private RangeHighlighter[] myActionHighlighters = RangeHighlighter.EMPTY_ARRAY; - - public void highlight(ChangeType.ChangeSide changeSide, Editor editor, ChangeType type) { - LOG.assertTrue(myEditor == null || editor == myEditor); - removeHighlighters(); - myEditor = editor; - setHighlighter(changeSide, type); - } - - private MarkupModel getMarkupModel() { - return myEditor.getMarkupModel(); - } - - private void highlighterCreated(RangeHighlighter highlighter, TextAttributes attrs) { - if (attrs != null) { - highlighter.setErrorStripeMarkColor(attrs.getErrorStripeColor()); - } - myHighlighters.add(highlighter); - } - - @Nullable - public RangeHighlighter addLineHighlighter(int line, int layer, TextDiffType diffType) { - if (myEditor.getDocument().getTextLength() == 0) return null; - RangeHighlighter highlighter = getMarkupModel().addLineHighlighter(line, layer, null); - highlighter.setLineSeparatorColor(diffType.getTextBackground(myEditor)); - highlighterCreated(highlighter, diffType.getTextAttributes(myEditor)); - return highlighter; - } - - @Nullable - public RangeHighlighter addRangeHighlighter(int start, int end, int layer, TextDiffType type, HighlighterTargetArea targetArea) { - if (getMarkupModel().getDocument().getTextLength() == 0) return null; - TextAttributes attributes = type.getTextAttributes(myEditor); - RangeHighlighter highlighter = getMarkupModel().addRangeHighlighter(start, end, layer, attributes, targetArea); - highlighterCreated(highlighter, attributes); - return highlighter; - } - - private void setHighlighter(ChangeType.ChangeSide changeSide, ChangeType type) { - myMainHighlighter = type.addMarker(changeSide, this); - updateAction(); - } - - public Editor getEditor() { - return myEditor; - } - - public void removeHighlighters() { - if (myEditor == null) { - LOG.assertTrue(myHighlighters.isEmpty()); - LOG.assertTrue(myMainHighlighter == null); - return; - } - for (RangeHighlighter highlighter : myHighlighters) { - highlighter.dispose(); - } - myHighlighters.clear(); - removeActionHighlighters(); - myMainHighlighter = null; - } - - private void removeActionHighlighters() { - for (RangeHighlighter actionHighlighter : myActionHighlighters) { - actionHighlighter.dispose(); - } - myActionHighlighters = RangeHighlighter.EMPTY_ARRAY; - } - - public void setActions(AnAction[] action) { - myActions = action; - updateAction(); - } - - private void updateAction() { - removeActionHighlighters(); - if (myMainHighlighter != null && myActions != null && myActions.length > 0) { - myActionHighlighters = new RangeHighlighter[myActions.length]; - for (int i = 0; i < myActionHighlighters.length; i++) { - RangeHighlighter highlighter = cloneMainHighlighter(myMainHighlighter); - highlighter.setGutterIconRenderer(new GutterActionRenderer(myActions[i])); - myActionHighlighters[i] = highlighter; - } - } - } - - private RangeHighlighter cloneMainHighlighter(@NotNull RangeHighlighter mainHighlighter) { - RangeHighlighter highlighter = myEditor.getMarkupModel().addRangeHighlighter(mainHighlighter.getStartOffset(), mainHighlighter.getEndOffset(), mainHighlighter.getLayer(), - null, mainHighlighter.getTargetArea()); - // TODO[dyoma] copy greedyToLeft and greedyToRight - return highlighter; - } - - public void updateHighlighter(ChangeType.ChangeSide changeSide, ChangeType type) { - LOG.assertTrue(myEditor != null); - removeHighlighters(); - setHighlighter(changeSide, type); - } - } - - protected static class Side extends ChangeType.ChangeSide { + protected static class SimpleChangeSide extends ChangeSide { private final FragmentSide mySide; private final DiffRangeMarker myRange; - private final HighlighterHolder myHighlighterHolder = new HighlighterHolder(); + private final ChangeHighlighterHolder myHighlighterHolder = new ChangeHighlighterHolder(); - public Side(FragmentSide side, DiffRangeMarker rangeMarker) { + public SimpleChangeSide(FragmentSide side, DiffRangeMarker rangeMarker) { mySide = side; myRange = rangeMarker; } @@ -256,7 +167,7 @@ public abstract class Change { return myRange; } - public HighlighterHolder getHighlighterHolder() { + public ChangeHighlighterHolder getHighlighterHolder() { return myHighlighterHolder; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java new file mode 100644 index 000000000000..137aac7cc6d6 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2012 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.diff.impl.incrementalMerge; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.diff.impl.util.GutterActionRenderer; +import com.intellij.openapi.diff.impl.util.TextDiffType; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.markup.HighlighterTargetArea; +import com.intellij.openapi.editor.markup.MarkupModel; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; + +/** + * Incorporates highlighting stuff of a Change. + * + * @author Kirill Likhodedov + */ +class ChangeHighlighterHolder { + + private static final Logger LOG = Logger.getInstance(ChangeHighlighterHolder.class); + + private Editor myEditor; + private final ArrayList myHighlighters = new ArrayList(3); + private RangeHighlighter myMainHighlighter = null; + private AnAction[] myActions; + private RangeHighlighter[] myActionHighlighters = RangeHighlighter.EMPTY_ARRAY; + + public void highlight(ChangeSide changeSide, Editor editor, ChangeType type) { + LOG.assertTrue(myEditor == null || editor == myEditor); + removeHighlighters(); + myEditor = editor; + setHighlighter(changeSide, type); + } + + private MarkupModel getMarkupModel() { + return myEditor.getMarkupModel(); + } + + private void highlighterCreated(RangeHighlighter highlighter, TextAttributes attrs) { + if (attrs != null) { + highlighter.setErrorStripeMarkColor(attrs.getErrorStripeColor()); + } + myHighlighters.add(highlighter); + } + + @Nullable + public RangeHighlighter addLineHighlighter(int line, int layer, TextDiffType diffType) { + if (myEditor.getDocument().getTextLength() == 0) return null; + RangeHighlighter highlighter = getMarkupModel().addLineHighlighter(line, layer, null); + highlighter.setLineSeparatorColor(diffType.getTextBackground(myEditor)); + highlighterCreated(highlighter, diffType.getTextAttributes(myEditor)); + return highlighter; + } + + @Nullable + public RangeHighlighter addRangeHighlighter(int start, int end, int layer, TextDiffType type, HighlighterTargetArea targetArea) { + if (getMarkupModel().getDocument().getTextLength() == 0) return null; + TextAttributes attributes = type.getTextAttributes(myEditor); + RangeHighlighter highlighter = getMarkupModel().addRangeHighlighter(start, end, layer, attributes, targetArea); + highlighterCreated(highlighter, attributes); + return highlighter; + } + + private void setHighlighter(ChangeSide changeSide, ChangeType type) { + myMainHighlighter = type.addMarker(changeSide, this); + updateAction(); + } + + public Editor getEditor() { + return myEditor; + } + + public void removeHighlighters() { + if (myEditor == null) { + LOG.assertTrue(myHighlighters.isEmpty()); + LOG.assertTrue(myMainHighlighter == null); + return; + } + for (RangeHighlighter highlighter : myHighlighters) { + highlighter.dispose(); + } + myHighlighters.clear(); + removeActionHighlighters(); + myMainHighlighter = null; + } + + private void removeActionHighlighters() { + for (RangeHighlighter actionHighlighter : myActionHighlighters) { + actionHighlighter.dispose(); + } + myActionHighlighters = RangeHighlighter.EMPTY_ARRAY; + } + + public void setActions(AnAction[] action) { + myActions = action; + updateAction(); + } + + private void updateAction() { + removeActionHighlighters(); + if (myMainHighlighter != null && myActions != null && myActions.length > 0) { + myActionHighlighters = new RangeHighlighter[myActions.length]; + for (int i = 0; i < myActionHighlighters.length; i++) { + RangeHighlighter highlighter = cloneMainHighlighter(myMainHighlighter); + highlighter.setGutterIconRenderer(new GutterActionRenderer(myActions[i])); + myActionHighlighters[i] = highlighter; + } + } + } + + private RangeHighlighter cloneMainHighlighter(@NotNull RangeHighlighter mainHighlighter) { + return myEditor.getMarkupModel().addRangeHighlighter(mainHighlighter.getStartOffset(), mainHighlighter.getEndOffset(), mainHighlighter.getLayer(), + null, mainHighlighter.getTargetArea()); + } + + public void updateHighlighter(ChangeSide changeSide, ChangeType type) { + LOG.assertTrue(myEditor != null); + removeHighlighters(); + setHighlighter(changeSide, type); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeSide.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeSide.java new file mode 100644 index 000000000000..cc2942aeadbb --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeSide.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2012 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.diff.impl.incrementalMerge; + +import com.intellij.openapi.diff.impl.util.DocumentUtil; + +/** +* @author Kirill Likhodedov +*/ +public abstract class ChangeSide { + + public int getStart() { + return getRange().getStartOffset(); + } + + public int getStartLine() { + return DocumentUtil.getStartLine(getRange()); + } + + public String getText() { + return DocumentUtil.getText(getRange()); + } + + public int getEndLine() { + return DocumentUtil.getEndLine(getRange()); + } + + public abstract DiffRangeMarker getRange(); + + public abstract ChangeHighlighterHolder getHighlighterHolder(); + + public boolean contains(int offset) { + return getStart() <= offset && offset < getEnd(); + } + + public int getEnd() { + return getRange().getEndOffset(); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java index fceefcf3cdf3..38382b003050 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeType.java @@ -34,6 +34,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; public class ChangeType { + private static final int LAYER = HighlighterLayer.SELECTION - 1; private static final ChangeType INSERT = new ChangeType(TextDiffType.INSERT); private static final ChangeType DELETED = new ChangeType(TextDiffType.DELETED); @@ -46,7 +47,7 @@ public class ChangeType { myDiffType = diffType; } - public RangeHighlighter addMarker(ChangeSide changeSide, MarkupHolder markup) { + public RangeHighlighter addMarker(ChangeSide changeSide, ChangeHighlighterHolder markup) { String text = changeSide.getText(); if (text != null && text.length() > 0) return addBlock(text, changeSide, markup, myDiffType); else return addLine(markup, changeSide.getStartLine(), myDiffType, SeparatorPlacement.TOP); @@ -58,16 +59,17 @@ public class ChangeType { public TextDiffType getTextDiffType() { return getTypeKey(); } - private static RangeHighlighter addBlock(String text, ChangeSide changeSide, MarkupHolder markup, TextDiffType diffType) { + private static RangeHighlighter addBlock(String text, ChangeSide changeSide, ChangeHighlighterHolder markup, TextDiffType diffType) { int length = text.length(); int start = changeSide.getStart(); int end = start + length; - RangeHighlighter highlighter = markup.addRangeHighlighter( - start, end, ChangeType.LAYER, diffType, HighlighterTargetArea.EXACT_RANGE); + RangeHighlighter highlighter = markup.addRangeHighlighter(start, end, ChangeType.LAYER, diffType, HighlighterTargetArea.EXACT_RANGE); highlighter.setLineSeparatorPlacement(SeparatorPlacement.TOP); highlighter.setLineMarkerRenderer(LineRenderer.top()); highlighter.setLineSeparatorColor(Color.GRAY); - if (text.charAt(length - 1) == '\n') end--; + if (text.charAt(length - 1) == '\n') { + end--; + } highlighter = markup.addRangeHighlighter(start, end, LAYER, TextDiffType.NONE, HighlighterTargetArea.EXACT_RANGE); highlighter.setLineSeparatorPlacement(SeparatorPlacement.BOTTOM); highlighter.setLineSeparatorColor(Color.GRAY); @@ -75,79 +77,30 @@ public class ChangeType { return highlighter; } - private static RangeHighlighter addLine(MarkupHolder markup, int line, TextDiffType type, SeparatorPlacement placement) { + @Nullable + private static RangeHighlighter addLine(ChangeHighlighterHolder markup, int line, TextDiffType type, SeparatorPlacement placement) { RangeHighlighter highlighter = markup.addLineHighlighter(line, LAYER, type); - if (highlighter == null) return null; + if (highlighter == null) { + return null; + } highlighter.setLineSeparatorPlacement(placement); return highlighter; } - public static ChangeType fromDiffFragment(DiffFragment fragment) { + static ChangeType fromDiffFragment(DiffFragment fragment) { if (fragment.getText1() == null) return INSERT; if (fragment.getText2() == null) return DELETED; return CHANGE; } - public static ChangeType fromRanges(@NotNull TextRange left, @NotNull TextRange right) { + static ChangeType fromRanges(@NotNull TextRange left, @NotNull TextRange right) { if (left.getLength() == 0) return INSERT; if (right.getLength() == 0) return DELETED; return CHANGE; } - public static void apply(@NotNull Project project, @NotNull RangeMarker original, @NotNull RangeMarker target) { - Document document = target.getDocument(); - if (!ReadonlyStatusHandler.ensureDocumentWritable(project, document)) return; - if (DocumentUtil.isEmpty(original)) { - int offset = target.getStartOffset(); - document.deleteString(offset, target.getEndOffset()); - } - String text = DocumentUtil.getText(original); - int startOffset = target.getStartOffset(); - if (DocumentUtil.isEmpty(target)) { - document.insertString(startOffset, text); - } else { - document.replaceString(startOffset, target.getEndOffset(), text); - } - } - public String toString() { return myDiffType.getDisplayName(); } - public interface MarkupHolder { - @Nullable - RangeHighlighter addLineHighlighter(int line, int layer, TextDiffType diffType); - @Nullable - RangeHighlighter addRangeHighlighter(int start, int end, int layer, TextDiffType type, HighlighterTargetArea targetArea); - } - - public static abstract class ChangeSide { - public int getStart() { - return getRange().getStartOffset(); - } - - public int getStartLine() { - return DocumentUtil.getStartLine(getRange()); - } - - public String getText() { - return DocumentUtil.getText(getRange()); - } - - public int getEndLine() { - return DocumentUtil.getEndLine(getRange()); - } - - public abstract DiffRangeMarker getRange(); - - public abstract Change.HighlighterHolder getHighlighterHolder(); - - public boolean contains(int offset) { - return getStart() <= offset && offset < getEnd(); - } - - public int getEnd() { - return getRange().getEndOffset(); - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java index 6b6b5ead435f..c6820c91dfbe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ConflictChange.java @@ -25,12 +25,12 @@ import com.intellij.openapi.util.TextRange; */ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListener { - private Side myOriginalSide; + private SimpleChangeSide myOriginalSide; private MergeConflict myConflict; public ConflictChange(MergeConflict conflict, FragmentSide mergeSide, TextRange range) { myConflict = conflict; - myOriginalSide = new Side(mergeSide, new DiffRangeMarker((DocumentEx)conflict.getOriginalDocument(mergeSide), range, this)); + myOriginalSide = new SimpleChangeSide(mergeSide, new DiffRangeMarker((DocumentEx)conflict.getOriginalDocument(mergeSide), range, this)); } protected void removeFromList() { @@ -38,7 +38,7 @@ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListe myConflict = null; } - public ChangeType.ChangeSide getChangeSide(FragmentSide side) { + public ChangeSide getChangeSide(FragmentSide side) { return isBranch(side) ? myOriginalSide : myConflict; } @@ -46,7 +46,7 @@ class ConflictChange extends Change implements DiffRangeMarker.RangeInvalidListe return MergeList.BRANCH_SIDE == side; } - public Change.Side getOriginalSide() { + public SimpleChangeSide getOriginalSide() { return myOriginalSide; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java index be4062058467..ca18b0183b18 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/MergeConflict.java @@ -24,13 +24,13 @@ import org.jetbrains.annotations.NotNull; /** * Represents a merge conflict, i.e. two {@link ConflictChange conflicting changes}, one from left, another from right. */ -class MergeConflict extends ChangeType.ChangeSide implements DiffRangeMarker.RangeInvalidListener { +class MergeConflict extends ChangeSide implements DiffRangeMarker.RangeInvalidListener { @NotNull private final MergeList myMergeList; @NotNull private final DiffRangeMarker myCommonRange; @NotNull private final ConflictChange myLeftChange; @NotNull private final ConflictChange myRightChange; - @NotNull private final Change.HighlighterHolder myCommonHighlighterHolder = new Change.HighlighterHolder(); + @NotNull private final ChangeHighlighterHolder myCommonHighlighterHolder = new ChangeHighlighterHolder(); MergeConflict(TextRange commonRange, MergeList mergeList, TextRange leftMarker, TextRange rightMarker) { myCommonRange = new DiffRangeMarker((DocumentEx)mergeList.getBaseDocument(),commonRange, this); @@ -39,7 +39,7 @@ class MergeConflict extends ChangeType.ChangeSide implements DiffRangeMarker.Ran myRightChange = new ConflictChange(this, FragmentSide.SIDE2, rightMarker); } - public Change.HighlighterHolder getHighlighterHolder() { + public ChangeHighlighterHolder getHighlighterHolder() { return myCommonHighlighterHolder; } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java index 7aeea7b63ecc..e0736c3bb373 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/SimpleChange.java @@ -24,25 +24,25 @@ import org.jetbrains.annotations.NotNull; class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListener{ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diff.impl.incrementalMerge.Change"); private final ChangeType myType; - private final Side[] mySides; + private final SimpleChangeSide[] mySides; private final ChangeList myChangeList; public SimpleChange(ChangeType type, @NotNull TextRange range1, @NotNull TextRange range2, ChangeList changeList) { - mySides = new Side[]{createSide(changeList, range1, FragmentSide.SIDE1), + mySides = new SimpleChangeSide[]{createSide(changeList, range1, FragmentSide.SIDE1), createSide(changeList, range2, FragmentSide.SIDE2)}; myType = type; myChangeList = changeList; } - private Change.Side createSide(ChangeList changeList, TextRange range1, FragmentSide side) { - return new Change.Side(side, new DiffRangeMarker((DocumentEx)changeList.getDocument(side), range1, this)); + private SimpleChangeSide createSide(ChangeList changeList, TextRange range1, FragmentSide side) { + return new SimpleChangeSide(side, new DiffRangeMarker((DocumentEx)changeList.getDocument(side), range1, this)); } protected void removeFromList() { myChangeList.remove(this); } - public ChangeType.ChangeSide getChangeSide(FragmentSide side) { + public ChangeSide getChangeSide(FragmentSide side) { return mySides[side.getIndex()]; } @@ -56,7 +56,7 @@ class SimpleChange extends Change implements DiffRangeMarker.RangeInvalidListene public void onRemovedFromList() { for (int i = 0; i < mySides.length; i++) { - Change.Side side = mySides[i]; + SimpleChangeSide side = mySides[i]; side.getRange().removeListener(this); side.getHighlighterHolder().removeHighlighters(); mySides[i] = null; From 44c2615aabd4681ca35f6ec3fea70f2fb9918aae Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 14:29:30 +0400 Subject: [PATCH 009/239] IDEA-85034 Git: "Contained i branches" shows always the "Loading status" --- plugins/git4idea/src/git4idea/GitBranch.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/git4idea/src/git4idea/GitBranch.java b/plugins/git4idea/src/git4idea/GitBranch.java index 074835767cf5..c17cbb76a972 100644 --- a/plugins/git4idea/src/git4idea/GitBranch.java +++ b/plugins/git4idea/src/git4idea/GitBranch.java @@ -253,6 +253,7 @@ public class GitBranch extends GitReference { final String prefix = "ref: refs/heads/"; return head.startsWith(prefix) ? new GitBranch(head.substring(prefix.length()), true, false) : null; } catch (IOException e) { + LOG.info(e); return null; } } From f88257bbffaddd3a79c03690022dea4c787fcab8 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 14:44:40 +0400 Subject: [PATCH 010/239] additionally for e159740, --- .../src/org/jetbrains/idea/svn/history/FirstInBranch.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index 4e03b8a87246..81c410f2c0fd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -80,9 +80,11 @@ public class FirstInBranch implements Runnable { final SVNLogClient logClient = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public SVNLogClient compute() { + if (myVcs.getProject().isDisposed()) return null; return myVcs.createLogClient(); } }); + if (logClient == null) return; final long start1 = getStart(logClient, branchURL); if (start1 > 0) { final SVNRevision start1Rev = SVNRevision.create(start1); From 7585d622a9a60ba5f3fe7811949be21b73bd2a29 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 15:14:15 +0400 Subject: [PATCH 011/239] IDEA-86767 Compare two text files shows no differences, while files are different (files were too big, and comparison was interrupted, but the messages was not shown) --- .../src/com/intellij/openapi/diff/impl/DiffPanelImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java index bd943bce6e3f..6c32190fcc02 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java @@ -363,7 +363,7 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid } public boolean hasDifferences() { - return getLineBlocks().getCount() > 0; + return getLineBlocks().getCount() > 0 || myNotCalculateDiffPanel != null; } public JComponent getPreferredFocusedComponent() { From 64c27b654de455de81aad18a283b4754195247ac Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 14:00:06 +0400 Subject: [PATCH 012/239] name suggestion fields in groovy introduce refactorings --- .../constant/GrIntroduceConstantDialog.form | 2 +- .../constant/GrIntroduceConstantDialog.java | 22 +++++++---------- .../field/GrIntroduceFieldDialog.form | 2 +- .../field/GrIntroduceFieldDialog.java | 24 +++++++------------ .../parameter/GrIntroduceParameterDialog.java | 17 ++++++------- .../GroovyIntroduceVariableDialog.java | 19 ++++++--------- 6 files changed, 32 insertions(+), 54 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.form index 349da4cb4b9f..48411b87b314 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.form @@ -41,7 +41,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java index 7e9522c94ada..ac6dc350b332 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java @@ -21,7 +21,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; @@ -36,11 +35,12 @@ import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.introduceField.IntroduceConstantHandler; import com.intellij.refactoring.ui.JavaVisibilityPanel; +import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.ui.RecentsManager; import com.intellij.ui.ReferenceEditorComboWithBrowseButton; -import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; @@ -85,7 +85,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper private JPanel myPanel; private GrTypeComboBox myTypeCombo; private ReferenceEditorComboWithBrowseButton myTargetClassEditor; - private TextFieldWithAutoCompletion myNameField; + private NameSuggestionsField myNameField; private JavaVisibilityPanel myJavaVisibilityPanel; private JPanel myTargetClassPanel; private JLabel myTargetClassLabel; @@ -193,11 +193,9 @@ public class GrIntroduceConstantDialog extends DialogWrapper } }, KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.ALT_MASK), JComponent.WHEN_IN_FOCUSED_WINDOW); - myNameField.addDocumentListener(new DocumentListener() { - public void beforeDocumentChange(DocumentEvent event) { - } - - public void documentChanged(DocumentEvent event) { + myNameField.addDataChangedListener(new NameSuggestionsField.DataChanged() { + @Override + public void dataChanged() { updateOkStatus(); } }); @@ -227,7 +225,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper @Nullable @Override public String getName() { - return myNameField.getText().trim(); + return myNameField.getEnteredName(); } @Override @@ -260,11 +258,7 @@ public class GrIntroduceConstantDialog extends DialogWrapper String[] possibleNames = GroovyNameSuggestionUtil.suggestVariableNames(myContext.getExpression(), new GroovyVariableValidator(myContext), true); ContainerUtil.addAll(names, possibleNames); - myNameField = TextFieldWithAutoCompletion.create(myContext.getProject(), names, null, true); - if (names.size()>0) { - myNameField.setText(names.get(0)); - myNameField.selectAll(); - } + myNameField = new NameSuggestionsField(ArrayUtil.toStringArray(names), myContext.getProject(), GroovyFileType.GROOVY_FILE_TYPE); GrTypeComboBox.registerUpDownHint(myNameField, myTypeCombo); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.form index f60e654bfc8c..cf7f8fabf7d1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.form @@ -32,7 +32,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java index 3af3e76a8305..108de3cd6a8c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java @@ -15,20 +15,20 @@ */ package org.jetbrains.plugins.groovy.refactoring.introduce.field; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.refactoring.util.RadioUpDownListener; -import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; @@ -60,7 +60,7 @@ import static com.intellij.refactoring.introduceField.IntroduceFieldHandler.REFA public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduceDialog, GrIntroduceFieldSettings { private JPanel myContentPane; - private TextFieldWithAutoCompletion myNameField; + private NameSuggestionsField myNameField; private JRadioButton myPrivateRadioButton; private JRadioButton myProtectedRadioButton; private JRadioButton myPublicRadioButton; @@ -131,13 +131,9 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce myReplaceAllOccurrencesCheckBox.setVisible(false); } - myNameField.addDocumentListener(new DocumentListener() { + myNameField.addDataChangedListener(new NameSuggestionsField.DataChanged() { @Override - public void beforeDocumentChange(DocumentEvent event) { - } - - @Override - public void documentChanged(DocumentEvent event) { + public void dataChanged() { validateOKAction(); } }); @@ -265,11 +261,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce list.add(var.getName()); } ContainerUtil.addAll(list, possibleNames); - myNameField = TextFieldWithAutoCompletion.create(myContext.getProject(), list, null, true); - if (list.size()>0) { - myNameField.setText(list.get(0)); - myNameField.selectAll(); - } + myNameField = new NameSuggestionsField(ArrayUtil.toStringArray(list), myContext.getProject(), GroovyFileType.GROOVY_FILE_TYPE); if (expression == null) { myTypeComboBox = GrTypeComboBox.createTypeComboBoxWithDefType(var.getDeclaredType() @@ -319,7 +311,7 @@ public class GrIntroduceFieldDialog extends DialogWrapper implements GrIntroduce @Override @NotNull public String getName() { - return myNameField.getText().trim(); + return myNameField.getEnteredName(); } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java index 4177581c4b8b..c5b6ed01158e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java @@ -32,9 +32,10 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.ui.NameSuggestionsField; import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.TextFieldWithAutoCompletion; import com.intellij.ui.components.JBRadioButton; +import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; @@ -42,6 +43,7 @@ import gnu.trove.TIntArrayList; import gnu.trove.TObjectIntHashMap; import gnu.trove.TObjectIntProcedure; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -77,7 +79,7 @@ import static com.intellij.refactoring.IntroduceParameterRefactoring.*; public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntroduceDialog { private GrTypeComboBox myTypeComboBox; - private TextFieldWithAutoCompletion myNameSuggestionsField; + private NameSuggestionsField myNameSuggestionsField; private JCheckBox myDeclareFinalCheckBox; private JCheckBox myDelegateViaOverloadingMethodCheckBox; private JBRadioButton myDoNotReplaceRadioButton; @@ -342,7 +344,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro return returnType; } - private TextFieldWithAutoCompletion createNameField(GrVariable var, GrExpression expr) { + private NameSuggestionsField createNameField(GrVariable var, GrExpression expr) { String[] possibleNames; if (expr != null) { final GrIntroduceContext @@ -366,12 +368,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro } ContainerUtil.addAll(names, possibleNames); - TextFieldWithAutoCompletion result = TextFieldWithAutoCompletion.create(myProject, names, null, true); - if (names.size() > 0) { - result.setText(names.get(0)); - result.selectAll(); - } - return result; + return new NameSuggestionsField(ArrayUtil.toStringArray(names), myProject, GroovyFileType.GROOVY_FILE_TYPE); } private void initReplaceFieldsWithGetters(JavaRefactoringSettings settings) { @@ -510,7 +507,7 @@ public class GrIntroduceParameterDialog extends DialogWrapper implements GrIntro } private String getEnteredName() { - return myNameSuggestionsField.getText().trim(); + return myNameSuggestionsField.getEnteredName(); } private void saveSettings() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableDialog.java index aa47fcf00fb1..2052ff190b9a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GroovyIntroduceVariableDialog.java @@ -22,10 +22,12 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.psi.PsiType; import com.intellij.refactoring.HelpID; -import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.refactoring.ui.NameSuggestionsField; +import com.intellij.util.ArrayUtil; import com.intellij.util.ui.GridBag; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil; @@ -48,7 +50,7 @@ public class GroovyIntroduceVariableDialog extends DialogWrapper implements GrIn private final int myOccurrencesCount; private final GrIntroduceVariableHandler.Validator myValidator; - private TextFieldWithAutoCompletion myNameField; + private NameSuggestionsField myNameField; private JCheckBox myCbIsFinal; private JCheckBox myCbReplaceAllOccurrences; private GrTypeComboBox myTypeComboBox; @@ -142,7 +144,7 @@ public class GroovyIntroduceVariableDialog extends DialogWrapper implements GrIn @Nullable protected String getEnteredName() { - return myNameField.getText().trim(); + return myNameField.getEnteredName(); } protected boolean isReplaceAllOccurrences() { @@ -158,17 +160,10 @@ public class GroovyIntroduceVariableDialog extends DialogWrapper implements GrIn return myTypeComboBox.getSelectedType(); } - private TextFieldWithAutoCompletion setUpNameComboBox() { + private NameSuggestionsField setUpNameComboBox() { List possibleNames = Arrays.asList(GroovyNameSuggestionUtil.suggestVariableNames(myExpression, myValidator)); - TextFieldWithAutoCompletion result = TextFieldWithAutoCompletion.create(myProject, possibleNames, null, true); - - if (possibleNames.size() > 0) { - result.setText(possibleNames.get(0)); - result.selectAll(); - } - - return result; + return new NameSuggestionsField(ArrayUtil.toStringArray(possibleNames), myProject, GroovyFileType.GROOVY_FILE_TYPE); } public JComponent getPreferredFocusedComponent() { From aebfdd2f0dfcb3b6df668ce38db772b1ece001f8 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 14:54:39 +0400 Subject: [PATCH 013/239] @TypeChecked --- .../plugins/groovy/lang/psi/impl/GroovyPsiManager.java | 2 ++ .../plugins/groovy/lang/psi/util/GroovyCommonClassNames.java | 1 + 2 files changed, 3 insertions(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java index f14ad91f7f9c..a7339849bec0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java @@ -137,6 +137,8 @@ public class GroovyPsiManager { if (list != null) { PsiAnnotation annotation = list.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_COMPILE_STATIC); if (annotation != null) return true; + PsiAnnotation typeChecked = list.findAnnotation(GroovyCommonClassNames.GROOVY_TRANSFORM_TYPE_CHECKED); + if (typeChecked != null) return true; } PsiClass aClass = member.getContainingClass(); if (aClass != null) return isCompileStatic(aClass); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java index f6e040e36eff..851927168bdb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyCommonClassNames.java @@ -52,6 +52,7 @@ public final class GroovyCommonClassNames { @NonNls public static final String GROOVY_UTIL_TEST_CASE = "groovy.util.GroovyTestCase"; @NonNls public static final String GROOVY_LANG_SINGLETON = "groovy.lang.Singleton"; @NonNls public static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic"; + @NonNls public static final String GROOVY_TRANSFORM_TYPE_CHECKED = "groovy.transform.TypeChecked"; private GroovyCommonClassNames() { From c5451cdd3476650e0ab6abee634514732e6706c8 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 14:56:09 +0400 Subject: [PATCH 014/239] correct gui layout for GroovyCreateClassDialog --- .../intentions/GroovyCreateClassDialog.form | 6 ++-- .../intentions/GroovyCreateClassDialog.java | 29 +++++++------------ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.form index 291244fad4b1..ed775082facc 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.form @@ -34,9 +34,9 @@ - + - + @@ -50,7 +50,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.java index 781e1963eac4..5cb1196bcd38 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GroovyCreateClassDialog.java @@ -22,6 +22,8 @@ import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.event.DocumentAdapter; +import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -30,16 +32,15 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiNameHelper; import com.intellij.psi.PsiPackage; import com.intellij.refactoring.util.RefactoringMessageUtil; -import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.EditorTextField; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle; import javax.swing.*; -import javax.swing.event.DocumentEvent; -import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; @@ -48,7 +49,7 @@ import java.awt.event.KeyEvent; public class GroovyCreateClassDialog extends DialogWrapper { private JPanel myContentPane; private JLabel myInformationLabel; - private MySizeTextField myPackageTextField; + private EditorTextField myPackageTextField; private JButton myPackageChooseButton; private PsiDirectory myTargetDirectory; private final Project myProject; @@ -86,26 +87,18 @@ public class GroovyCreateClassDialog extends DialogWrapper { } private void createUIComponents() { - myPackageTextField = new MySizeTextField(); + myPackageTextField = new EditorTextField(); myPackageChooseButton = new FixedSizeButton(myPackageTextField); } - public static class MySizeTextField extends JTextField { - public Dimension getPreferredSize() { - Dimension size = super.getPreferredSize(); - FontMetrics fontMetrics = getFontMetrics(getFont()); - size.width = fontMetrics.charWidth('a') * 40; - return size; - } - } - @Nullable protected JComponent createCenterPanel() { - myPackageTextField.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { - getOKAction().setEnabled(JavaPsiFacade.getInstance(myProject).getNameHelper().isQualifiedName(getPackageName()) || - "".equals(getPackageName())); + @Override + public void documentChanged(DocumentEvent e) { + PsiNameHelper nameHelper = JavaPsiFacade.getInstance(myProject).getNameHelper(); + String packageName = getPackageName(); + getOKAction().setEnabled(nameHelper.isQualifiedName(packageName) || packageName != null && packageName.isEmpty()); } }); From 4b08b2c6f282faf5ff66475e76644304cb1a7e65 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Thu, 31 May 2012 16:20:56 +0400 Subject: [PATCH 015/239] IDEA-86521 --- .../designer/propertyTable/PropertyTable.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java index 83b245867218..3fe2aab4930a 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/propertyTable/PropertyTable.java @@ -290,7 +290,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi int indexToSelect = -1; int size = propertyPath.size(); for (int i = 0; i < size; i++) { - int index = findProperty(myProperties, propertyPath.get(i)); + int index = findFullPathProperty(myProperties, propertyPath.get(i)); if (index == -1) { break; } @@ -332,7 +332,7 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi for (Iterator I = myProperties.iterator(); I.hasNext(); ) { Property property = I.next(); - int index = findProperty(properties, property); + int index = findFullPathProperty(properties, property); if (index == -1) { I.remove(); continue; @@ -408,6 +408,32 @@ public final class PropertyTable extends JBTable implements ComponentSelectionLi return -1; } + private static int findFullPathProperty(List properties, Property property) { + Property parent = property.getParent(); + if (parent == null) { + return findProperty(properties, property); + } + + String name = getFullPathName(property); + int size = properties.size(); + + for (int i = 0; i < size; i++) { + if (name.equals(getFullPathName(properties.get(i)))) { + return i; + } + } + + return -1; + } + + private static String getFullPathName(Property property) { + StringBuilder builder = new StringBuilder(); + for (; property != null; property = property.getParent()) { + builder.insert(0, ".").insert(0, property.getName()); + } + return builder.toString(); + } + public static void moveProperty(List source, String name, List destination, int index) { Property property = extractProperty(source, name); if (property != null) { From 886027be421d1889afe1814b630706c671244fe9 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 31 May 2012 16:24:27 +0400 Subject: [PATCH 016/239] IDEA-86103 Reimport maven module if dependency list is changed --- .../idea/maven/importing/MavenImporter.java | 4 ++ .../maven/importing/MavenModuleImporter.java | 33 ++++++++++--- .../maven/importing/MavenProjectImporter.java | 46 ++++++++++++------- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java index 843f8d2caa97..8853355bb8c3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenImporter.java @@ -125,6 +125,10 @@ public abstract class MavenImporter { Map mavenProjectToModuleName, List postTasks); + public boolean processChangedModulesOnly() { + return true; + } + public void collectSourceFolders(MavenProject mavenProject, List result) { } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java index 00ca4d806dbd..7a51c9665b5c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java @@ -22,7 +22,6 @@ import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; @@ -31,6 +30,7 @@ import com.intellij.openapi.vfs.encoding.EncodingManager; import com.intellij.pom.java.LanguageLevel; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.model.MavenConstants; import org.jetbrains.idea.maven.project.*; @@ -45,6 +45,8 @@ public class MavenModuleImporter { private final Module myModule; private final MavenProjectsTree myMavenTree; private final MavenProject myMavenProject; + + @Nullable private final MavenProjectChanges myMavenProjectChanges; private final Map myMavenProjectToModuleName; private final MavenImportingSettings mySettings; @@ -53,14 +55,15 @@ public class MavenModuleImporter { public MavenModuleImporter(Module module, MavenProjectsTree mavenTree, - Pair mavenProjectWithChanges, + MavenProject mavenProject, + @Nullable MavenProjectChanges changes, Map mavenProjectToModuleName, MavenImportingSettings settings, MavenModifiableModelsProvider modifiableModelsProvider) { myModule = module; myMavenTree = mavenTree; - myMavenProject = mavenProjectWithChanges.first; - myMavenProjectChanges = mavenProjectWithChanges.second; + myMavenProject = mavenProject; + myMavenProjectChanges = changes; myMavenProjectToModuleName = mavenProjectToModuleName; mySettings = settings; myModifiableModelsProvider = modifiableModelsProvider; @@ -84,12 +87,21 @@ public class MavenModuleImporter { final ModuleType moduleType = ModuleType.get(myModule); for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + if (importer.getModuleType() == moduleType) { // facets use FacetConfiguration and like that do not have modifiable models, // therefore we have to take write lock MavenUtil.invokeAndWaitWriteAction(myModule.getProject(), new Runnable() { public void run() { - importer.preProcess(myModule, myMavenProject, myMavenProjectChanges, myModifiableModelsProvider); + importer.preProcess(myModule, myMavenProject, changes, myModifiableModelsProvider); } }); } @@ -100,6 +112,15 @@ public class MavenModuleImporter { final ModuleType moduleType = ModuleType.get(myModule); for (final MavenImporter importer : getSuitableImporters()) { + final MavenProjectChanges changes; + if (myMavenProjectChanges == null) { + if (importer.processChangedModulesOnly()) continue; + changes = MavenProjectChanges.NONE; + } + else { + changes = myMavenProjectChanges; + } + if (importer.getModuleType() == moduleType) { // facets use FacetConfiguration and like that do not have modifiable models, // therefore we have to take write lock @@ -110,7 +131,7 @@ public class MavenModuleImporter { myRootModelAdapter, myMavenTree, myMavenProject, - myMavenProjectChanges, + changes, myMavenProjectToModuleName, postTasks); } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java index f4ff8d86fe24..ed73c334a3d5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java @@ -19,7 +19,9 @@ import com.intellij.compiler.CompilerConfiguration; import com.intellij.compiler.CompilerConfigurationImpl; import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.module.*; +import com.intellij.openapi.module.ModifiableModuleModel; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModifiableRootModel; @@ -36,6 +38,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.Stack; import gnu.trove.THashMap; import gnu.trove.THashSet; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.*; import org.jetbrains.idea.maven.utils.MavenLog; @@ -46,8 +49,6 @@ import org.jetbrains.idea.maven.utils.MavenUtil; import java.io.File; import java.io.IOException; import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class MavenProjectImporter { private final Project myProject; @@ -397,36 +398,48 @@ public class MavenProjectImporter { private void importModules(final List postTasks) { Map projectsWithChanges = myProjectsToImportWithChanges; - Set projects = projectsWithChanges.keySet(); Set projectsWithNewlyCreatedModules = new THashSet(); - for (MavenProject each : projects) { + for (MavenProject each : projectsWithChanges.keySet()) { if (ensureModuleCreated(each)) { projectsWithNewlyCreatedModules.add(each); } } - final Map moduleImporters = new THashMap(); + List modulesToMavenize = new ArrayList(); + List importers = new ArrayList(); + for (Map.Entry each : projectsWithChanges.entrySet()) { MavenProject project = each.getKey(); Module module = myMavenProjectToModule.get(project); boolean isNewModule = projectsWithNewlyCreatedModules.contains(project); - MavenModuleImporter moduleImporter = createModuleImporter(module, Pair.create(project, each.getValue())); - moduleImporters.put(module, moduleImporter); + MavenModuleImporter moduleImporter = createModuleImporter(module, project, each.getValue()); + modulesToMavenize.add(module); + importers.add(moduleImporter); moduleImporter.config(isNewModule); } - for (MavenProject each : projects) { - moduleImporters.get(myMavenProjectToModule.get(each)).preConfigFacets(); - } - for (MavenProject each : projects) { - moduleImporters.get(myMavenProjectToModule.get(each)).configFacets(postTasks); + for (MavenProject project : myAllProjects) { + if (!projectsWithChanges.containsKey(project)) { + Module module = myMavenProjectToModule.get(project); + if (module == null) continue; + + importers.add(createModuleImporter(module, project, null)); + } } - setMavenizedModules(moduleImporters.keySet(), true); + for (MavenModuleImporter importer : importers) { + importer.preConfigFacets(); + } + + for (MavenModuleImporter importer : importers) { + importer.configFacets(postTasks); + } + + setMavenizedModules(modulesToMavenize, true); } private void setMavenizedModules(final Collection modules, final boolean mavenized) { @@ -466,10 +479,11 @@ public class MavenProjectImporter { }); } - private MavenModuleImporter createModuleImporter(Module module, Pair projectWithChanges) { + private MavenModuleImporter createModuleImporter(Module module, MavenProject mavenProject, @Nullable MavenProjectChanges changes) { return new MavenModuleImporter(module, myProjectsTree, - projectWithChanges, + mavenProject, + changes, myMavenProjectToModuleName, myImportingSettings, myModelsProvider); From 1e0976b42c9dbacc7f7686f0df66a2faaded1ef9 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 16:55:55 +0400 Subject: [PATCH 017/239] IDEA-86247 No feedback after loading a patch file --- .../intellij/openapi/vcs/ZipperUpdater.java | 12 ++++++++++ .../patch/ApplyPatchDifferentiatedDialog.java | 23 +++++++++++++++---- .../vcs/changes/ui/ChangesTreeList.java | 5 ++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipperUpdater.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipperUpdater.java index 0ab7a86c4e6f..6f2d851b1677 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipperUpdater.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ZipperUpdater.java @@ -25,6 +25,7 @@ public class ZipperUpdater { private boolean myRaised; private final Object myLock = new Object(); private final int myDelay; + private boolean myIsEmpty; public ZipperUpdater(final int delay, Disposable parentDisposable) { this(delay, Alarm.ThreadToUse.SHARED_THREAD, parentDisposable); @@ -32,6 +33,7 @@ public class ZipperUpdater { public ZipperUpdater(final int delay, final Alarm.ThreadToUse threadToUse, Disposable parentDisposable) { myDelay = delay; + myIsEmpty = true; myAlarm = new Alarm(threadToUse, parentDisposable); } @@ -44,6 +46,7 @@ public class ZipperUpdater { if (myAlarm.isDisposed()) return; final boolean wasRaised = myRaised; myRaised = true; + myIsEmpty = false; if (! wasRaised) { myAlarm.addRequest(new Runnable() { public void run() { @@ -52,12 +55,21 @@ public class ZipperUpdater { myRaised = false; } runnable.run(); + synchronized (myLock) { + myIsEmpty = ! myRaised; + } } }, urgent ? 0 : myDelay); } } } + public boolean isEmpty() { + synchronized (myLock) { + return myIsEmpty; + } + } + public void stop() { myAlarm.cancelAllRequests(); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index 22610770973a..30aca85f19e6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -148,7 +148,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myPatchFile.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { protected void textChanged(DocumentEvent e) { setPathFileChangeDefault(); - myLoadQueue.queue(myUpdater); + queueRequest(); } }); @@ -191,7 +191,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { public void contentsChanged(VirtualFileEvent event) { if (myRecentPathFileChange.get() != null && myRecentPathFileChange.get().getVf() != null && myRecentPathFileChange.get().getVf().equals(event.getFile())) { - myLoadQueue.queue(myUpdater); + queueRequest(); } } }; @@ -206,6 +206,11 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } } + private void queueRequest() { + paintBusy(true); + myLoadQueue.queue(myUpdater); + } + private void init(List patches, final LocalChangeList localChangeList) { final List matchedPathes = new AutoMatchIterator(myProject).execute(patches); @@ -284,7 +289,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { public void init(final VirtualFile patchFile) { myPatchFile.setText(patchFile.getPresentableUrl()); myRecentPathFileChange.set(new FilePresentation(patchFile)); - myLoadQueue.queue(myUpdater); + queueRequest(); } private class MyUpdater implements Runnable { @@ -309,6 +314,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myPatches.addAll(matchedPathes); myReader = patchReader; updateTree(true); + paintBusy(false); } }); } @@ -368,6 +374,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myChangesTreeList.setChangesToDisplay(Collections.emptyList()); myChangesTreeList.repaint(); myContainBasedChanges = false; + paintBusy(false); } @Override @@ -410,7 +417,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { group.add(new AnAction("Refresh", "Refresh", AllIcons.Actions.Sync) { @Override public void actionPerformed(AnActionEvent e) { - myLoadQueue.queue(myUpdater); + queueRequest(); } }); } @@ -445,6 +452,14 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { return myCenterPanel; } + private void paintBusy(final boolean requestPut) { + if (requestPut) { + myChangesTreeList.setPaintBusy(true); + } else { + myChangesTreeList.setPaintBusy(! myLoadQueue.isEmpty()); + } + } + private static class MyChangeTreeList extends ChangesTreeList { private MyChangeTreeList(Project project, Collection initiallyIncluded, diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index 4aa730b6880d..9cd1dd3fb7ed 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -927,4 +927,9 @@ public abstract class ChangesTreeList extends JPanel { public void setAlwaysExpandList(boolean alwaysExpandList) { myAlwaysExpandList = alwaysExpandList; } + + public void setPaintBusy(final boolean value) { + myTree.setPaintBusy(value); + myList.setPaintBusy(value); + } } From 5ba86ba03b96789fc30b94be691aa1b38aec5c3c Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 17:01:11 +0400 Subject: [PATCH 018/239] apply patch: always expand all nodes on new patch file contents is shown --- .../vcs/changes/patch/ApplyPatchDifferentiatedDialog.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index 30aca85f19e6..04c44c55c76a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -551,6 +551,9 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myChangesTreeList.setChangesToDisplay(changes); myChangesTreeList.setIncludedChanges(included); + if (doInitCheck) { + myChangesTreeList.expandAll(); + } myChangesTreeList.repaint(); if ((! doInitCheck) && patchesToSelect != null) { final List toSelect = new ArrayList(patchesToSelect.size()); From 4b3db7acdee21b152b909b53bd0d210b62608651 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 31 May 2012 15:40:51 +0200 Subject: [PATCH 019/239] rollback rollback --- .../ide/navigationToolbar/NavBarListener.java | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java index 634501e5e74b..bc8bb588ff35 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -20,13 +20,16 @@ import com.intellij.ide.actions.CopyAction; import com.intellij.ide.actions.CutAction; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.AnActionListener; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootEvent; import com.intellij.openapi.roots.ModuleRootListener; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.vcs.FileStatusListener; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.problems.WolfTheProblemSolver; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiTreeChangeEvent; @@ -36,10 +39,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.FocusEvent; -import java.awt.event.FocusListener; +import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; @@ -49,7 +49,7 @@ import java.util.List; */ public class NavBarListener extends WolfTheProblemSolver.ProblemListener implements ActionListener, FocusListener, FileStatusListener, AnActionListener, - PsiTreeChangeListener, ModuleRootListener, NavBarModelListener, PropertyChangeListener { + PsiTreeChangeListener, ModuleRootListener, NavBarModelListener, PropertyChangeListener, KeyListener { private static final String LISTENER = "NavBarListener"; private static final String BUS = "NavBarMessageBus"; private final NavBarPanel myPanel; @@ -71,6 +71,7 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener connection.subscribe(ProjectTopics.PROJECT_ROOTS, listener); connection.subscribe(NavBarModelListener.NAV_BAR, listener); panel.putClientProperty(BUS, connection); + panel.addKeyListener(listener); } static void unsubscribeFrom(NavBarPanel panel) { @@ -256,7 +257,46 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener || action instanceof CutAction; } + @Override + public void keyPressed(final KeyEvent e) { + if (!(e.isAltDown() || e.isMetaDown() || e.isControlDown() || myPanel.isNodePopupActive())) { + if (!Character.isLetter(e.getKeyChar())) { + return; + } + + final IdeFocusManager focusManager = IdeFocusManager.getInstance(myPanel.getProject()); + final ActionCallback firstCharTyped = new ActionCallback(); + focusManager.typeAheadUntil(firstCharTyped); + myPanel.moveDown(); + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + try { + final Robot robot = new Robot(); + final boolean shiftOn = e.isShiftDown(); + final int code = e.getKeyCode(); + if (shiftOn) { + robot.keyPress(KeyEvent.VK_SHIFT); + } + robot.keyPress(code); + robot.keyRelease(code); + + //don't release Shift + firstCharTyped.setDone(); + } + catch (AWTException ignored) { + } + } + }); + } + } + //---- Ignored + @Override + public void keyTyped(KeyEvent e) {} + + @Override + public void keyReleased(KeyEvent e) {} + @Override public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {} From fdea7504c0c25e3602b3bf8d3536ef3d9f6a502f Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 17:41:14 +0400 Subject: [PATCH 020/239] don't duplicate usages from field and accessors --- .../parameterToEntry/ConvertParameterToMapEntryIntention.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java index 29f8709945e9..f4f4aac8315e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java @@ -36,6 +36,7 @@ import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -445,7 +446,7 @@ public class ConvertParameterToMapEntryIntention extends Intention { .message("find.method.ro.closure.usages.0", owner instanceof GrClosableBlock ? CLOSURE_CAPTION : METHOD_CAPTION), true) { public void run(@NotNull final ProgressIndicator indicator) { final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(getProject()); - final Collection references = Collections.synchronizedList(new ArrayList()); + final Collection references = Collections.synchronizedSet(new HashSet()); final Processor consumer = new Processor() { @Override public boolean process(PsiReference psiReference) { From d8f82066b8b2cf4caca2ccdae8011f521713d740 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 17:41:40 +0400 Subject: [PATCH 021/239] correct constructors for converted scripts --- .../convertToJava/ClassItemGeneratorImpl.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index c54d192ffb42..13cf94b98900 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -20,7 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightMethodBuilder; -import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.codeInspection.noReturnMethod.MissingReturnInspection; @@ -41,6 +41,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConstantInitializer; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass; @@ -335,10 +336,11 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { if (typeDefinition instanceof GroovyScriptClass) { final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.project); final String name = typeDefinition.getName(); - result.add(factory.createConstructorFromText(name, new String[]{"groovy.lang.Binding"}, new String[]{"binding"}, "{super(binding);}", - typeDefinition)); - result.add( - factory.createConstructorFromText(name, ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.EMPTY_STRING_ARRAY, "{super();}", typeDefinition)); + GrTypeDefinition tempClass = factory.createTypeDefinition("class " + name + " extends groovy.lang.Script {\n" + + " def " + name + "(groovy.lang.Binding binding){ super(binding);}\n" + + " def " + name + "(){super();}\n" + + "}"); + ContainerUtil.addAll(result, tempClass.getCodeConstructors()); } return result; } From a2e79e6f17708cda9311099e30300e5a35b5f0b6 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Thu, 31 May 2012 17:42:14 +0400 Subject: [PATCH 022/239] fix NPE --- .../impl/signatures/GrClosureSignatureUtil.java | 16 +++++++++++----- .../convertToJava/ArgumentListGenerator.java | 1 + ...yIntroduceParameterMethodUsagesProcessor.java | 1 + .../java2groovy/OldReferencesResolver.java | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java index b3c3b8ca762a..24123e079bbe 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java @@ -639,6 +639,7 @@ public class GrClosureSignatureUtil { final HashMap> result = new HashMap>(); for (int i = 0; i < argInfos.length; i++) { ArgInfo info = argInfos[i]; + if (info == null) continue; for (PsiElement arg : info.args) { if (arg instanceof GrNamedArgument) { arg = ((GrNamedArgument)arg).getExpression(); @@ -719,12 +720,17 @@ public class GrClosureSignatureUtil { for (; i < innerMap.length; i++) { final ArgInfo innerArg = innerMap[i]; - List argList = new ArrayList(); - for (InnerArg arg : innerArg.args) { - argList.addAll(arg.list); + if (innerArg == null) { + map[i] = null; + } + else { + List argList = new ArrayList(); + for (InnerArg arg : innerArg.args) { + argList.addAll(arg.list); + } + boolean multiArg = innerArg.isMultiArg || argList.size() > 1; + map[i] = new ArgInfo(argList, multiArg); } - boolean multiArg = innerArg.isMultiArg || argList.size() > 1; - map[i] = new ArgInfo(argList, multiArg); } return map; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java index 32a160ac9383..8620f5902d26 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java @@ -75,6 +75,7 @@ class ArgumentListGenerator { boolean hasArgs = false; for (int i = 0; i < argInfos.length; i++) { GrClosureSignatureUtil.ArgInfo arg = argInfos[i]; + if (arg == null) continue; final GrClosureParameter param = params[i]; if (arg.isMultiArg ? generateMultiArg(arg, param, substitutor, project, context) : generateSingeArg(arg, param)) { hasArgs = true; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 10cf41aeee85..1493d3f73d0d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -169,6 +169,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP public boolean execute(final int paramNum) { try { final GrClosureSignatureUtil.ArgInfo actualArg = actualArgs[paramNum]; + if (actualArg == null) return true; for (PsiElement arg : actualArg.args) { arg.delete(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/OldReferencesResolver.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/OldReferencesResolver.java index fa72d5ae8e5c..0a4409106c8e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/OldReferencesResolver.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/OldReferencesResolver.java @@ -318,7 +318,7 @@ public class OldReferencesResolver { @NotNull private GrExpression getActualArg(int index) { - if (myActualArgs == null) { + if (myActualArgs == null || myActualArgs[index] == null) { final GrExpression[] arguments = myContext.getArgumentList().getExpressionArguments(); if (index < arguments.length) return arguments[index]; index -= arguments.length; From 16dcd0173bdf1ecc47d96e950da26db9df87b7de Mon Sep 17 00:00:00 2001 From: "andrey.zaytsev" Date: Thu, 31 May 2012 18:09:20 +0400 Subject: [PATCH 023/239] Visual Studio keymap fix --- platform/platform-resources/src/idea/Keymap_VisualStudio.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-resources/src/idea/Keymap_VisualStudio.xml b/platform/platform-resources/src/idea/Keymap_VisualStudio.xml index faa8875ec839..3a75f1eef983 100644 --- a/platform/platform-resources/src/idea/Keymap_VisualStudio.xml +++ b/platform/platform-resources/src/idea/Keymap_VisualStudio.xml @@ -170,6 +170,9 @@ + + + From 7497c65ab4f10d09527fefa350b61c11b5d812fb Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 31 May 2012 18:34:52 +0400 Subject: [PATCH 024/239] configurable cache size for stub indices + use int[] instead of TIntArrayList to minimize memory usage (most often this is one element array) --- .../src/com/intellij/psi/stubs/StubTree.java | 68 +++++++++++++------ .../intellij/psi/stubs/AbstractStubIndex.java | 2 + .../psi/stubs/StubIndexExtension.java | 2 + .../com/intellij/psi/stubs/StubIndexImpl.java | 54 ++++++++------- .../intellij/psi/stubs/StubUpdatingIndex.java | 20 +++--- 5 files changed, 91 insertions(+), 55 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java index d1021e2be84c..34aa9ee3a48e 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTree.java @@ -21,11 +21,11 @@ package com.intellij.psi.stubs; import com.intellij.openapi.util.Key; import gnu.trove.THashMap; -import gnu.trove.TIntArrayList; +import gnu.trove.TObjectObjectProcedure; +import gnu.trove.TObjectProcedure; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -64,11 +64,9 @@ public class StubTree { } @NotNull - public Map> indexStubTree() { - final Map> result = new HashMap>(); - + public Map> indexStubTree() { SerializationManager serializationManager = SerializationManager.getInstance(); - StubIndexSink sink = new StubIndexSink(result); + StubIndexSink sink = new StubIndexSink(); for (int i = 0, plainListSize = myPlainList.size(); i < plainListSize; i++) { final StubElement stub = myPlainList.get(i); @@ -76,31 +74,63 @@ public class StubTree { serializationManager.getSerializer(stub).indexStub(stub, sink); } - return result; + return sink.getResult(); } - private static class StubIndexSink implements IndexSink { - private final Map> myResult; + private static class StubIndexSink implements IndexSink, TObjectProcedure>,TObjectObjectProcedure { + private final THashMap> myResult = new THashMap>();; private int myStubIdx; - - public StubIndexSink(Map> result) { - myResult = result; - } + private Map myProcessingMap; @Override public void occurrence(@NotNull final StubIndexKey indexKey, @NotNull final Object value) { - Map map = myResult.get(indexKey); + Map map = myResult.get(indexKey); if (map == null) { - map = new THashMap(); + map = new THashMap(); myResult.put(indexKey, map); } - TIntArrayList list = map.get(value); + int[] list = map.get(value); if (list == null) { - list = new TIntArrayList(); - map.put(value, list); + map.put(value, new int[] {myStubIdx}); + } else { + int lastZero; + for(lastZero = list.length - 1; lastZero >=0 && list[lastZero] == 0; --lastZero); + ++lastZero; + + if (lastZero == list.length) { + int[] newlist = new int[Math.max(4, list.length << 1)]; + System.arraycopy(list, 0, newlist, 0, list.length); + lastZero = list.length; + map.put(value, list = newlist); + } + list[lastZero] = myStubIdx; } - list.add(myStubIdx); + } + + public Map> getResult() { + myResult.forEachValue(this); + return myResult; + } + + @Override + public boolean execute(Map object) { + myProcessingMap = object; + ((THashMap)object).forEachEntry(this); + return true; + } + + @Override + public boolean execute(Object a, int[] b) { + if (b.length == 1) return true; + int firstZero; + for(firstZero = 0; firstZero < b.length && b[firstZero] != 0; ++firstZero); + if (firstZero != b.length) { + int[] shorterList = new int[firstZero]; + System.arraycopy(b, 0, shorterList, 0, shorterList.length); + myProcessingMap.put(a, shorterList); + } + return true; } } } diff --git a/platform/lang-api/src/com/intellij/psi/stubs/AbstractStubIndex.java b/platform/lang-api/src/com/intellij/psi/stubs/AbstractStubIndex.java index 1d5c648f844d..4cc68a25392c 100644 --- a/platform/lang-api/src/com/intellij/psi/stubs/AbstractStubIndex.java +++ b/platform/lang-api/src/com/intellij/psi/stubs/AbstractStubIndex.java @@ -32,4 +32,6 @@ public abstract class AbstractStubIndex implements public Collection get(Key key, final Project project, final GlobalSearchScope scope) { return StubIndex.getInstance().get(getKey(), key, project, scope); } + + public int getCacheSize() { return 5; } } diff --git a/platform/lang-api/src/com/intellij/psi/stubs/StubIndexExtension.java b/platform/lang-api/src/com/intellij/psi/stubs/StubIndexExtension.java index 8ee1c2dbc253..741cab3f5247 100644 --- a/platform/lang-api/src/com/intellij/psi/stubs/StubIndexExtension.java +++ b/platform/lang-api/src/com/intellij/psi/stubs/StubIndexExtension.java @@ -34,4 +34,6 @@ public interface StubIndexExtension { @NotNull KeyDescriptor getKeyDescriptor(); + + int getCacheSize(); } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 05a5e6d08e00..54a83823712b 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -49,7 +49,6 @@ import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.THashMap; -import gnu.trove.TIntArrayList; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -128,8 +127,13 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe for (int attempt = 0; attempt < 2; attempt++) { try { - final MapIndexStorage storage = new MapIndexStorage(IndexInfrastructure.getStorageFile(indexKey), extension.getKeyDescriptor(), new StubIdExternalizer(), 2 * 1024); - final MemoryIndexStorage memStorage = new MemoryIndexStorage(storage); + final MapIndexStorage storage = new MapIndexStorage( + IndexInfrastructure.getStorageFile(indexKey), + extension.getKeyDescriptor(), + new StubIdExternalizer(), + extension.getCacheSize() + ); + final MemoryIndexStorage memStorage = new MemoryIndexStorage(storage); myIndices.put(indexKey, new MyIndex(memStorage)); break; } @@ -143,40 +147,38 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe return needRebuild; } - private static class StubIdExternalizer implements DataExternalizer { + private static class StubIdExternalizer implements DataExternalizer { @Override - public void save(final DataOutput out, @NotNull final TIntArrayList value) throws IOException { - int size = value.size(); + public void save(final DataOutput out, @NotNull final int[] value) throws IOException { + int size = value.length; if (size == 0) { DataInputOutputUtil.writeSINT(out, Integer.MAX_VALUE); } else if (size == 1) { - DataInputOutputUtil.writeSINT(out, -value.get(0)); + DataInputOutputUtil.writeSINT(out, -value[0]); } else { DataInputOutputUtil.writeSINT(out, size); for (int i = 0; i < size; i++) { - DataInputOutputUtil.writeINT(out, value.get(i)); + DataInputOutputUtil.writeINT(out, value[i]); } } } @NotNull @Override - public TIntArrayList read(final DataInput in) throws IOException { + public int[] read(final DataInput in) throws IOException { int size = DataInputOutputUtil.readSINT(in); if (size == Integer.MAX_VALUE) { - return new TIntArrayList(); + return new int[0]; } else if (size <= 0) { - TIntArrayList result = new TIntArrayList(1); - result.add(-size); - return result; + return new int[] {-size}; } else { - TIntArrayList result = new TIntArrayList(size); + int[] result = new int[size]; for (int i = 0; i < size; i++) { - result.add(DataInputOutputUtil.readINT(in)); + result[i] = DataInputOutputUtil.readINT(in); } return result; } @@ -213,13 +215,13 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe // disable up-to-date check to avoid locks on attempt to acquire index write lock while holding at the same time the readLock for this index FileBasedIndexImpl.disableUpToDateCheckForCurrentThread(); index.getReadLock().lock(); - final ValueContainer container = index.getData(key); + final ValueContainer container = index.getData(key); final FileBasedIndexImpl.ProjectIndexableFilesFilter projectFilesFilter = fileBasedIndex.projectIndexableFiles(project); - return container.forEach(new ValueContainer.ContainerAction() { + return container.forEach(new ValueContainer.ContainerAction() { @Override - public boolean perform(final int id, @NotNull final TIntArrayList value) { + public boolean perform(final int id, @NotNull final int[] value) { if (projectFilesFilter != null && !projectFilesFilter.contains(id)) return true; final VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); if (file == null || scope != null && !scope.contains(file)) { @@ -249,8 +251,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe return true; } final List> plained = stubTree.getPlainList(); - for (int i = 0; i < value.size(); i++) { - final StubElement stub = plained.get(value.get(i)); + for (int i = 0; i < value.length; i++) { + final StubElement stub = plained.get(value[i]); final ASTNode tree = psiFile.findTreeForStub(stubTree, stub); if (tree != null) { @@ -290,8 +292,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe } else { final List> plained = stubTree.getPlainList(); - for (int i = 0; i < value.size(); i++) { - final int stubTreeIndex = value.get(i); + for (int i = 0; i < value.length; i++) { + final int stubTreeIndex = value[i]; if (stubTreeIndex >= plained.size()) { final VirtualFile virtualFile = psiFile.getVirtualFile(); StubTree stubTreeFromIndex = StubTreeLoader.getInstance().readFromVFile(project, file); @@ -470,7 +472,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe index.flush(); } - public void updateIndex(@NotNull StubIndexKey key, int fileId, @NotNull final Map oldValues, @NotNull Map newValues) { + public void updateIndex(@NotNull StubIndexKey key, int fileId, @NotNull final Map oldValues, @NotNull Map newValues) { try { final MyIndex index = (MyIndex)myIndices.get(key); index.updateWithMap(fileId, newValues, new Callable>() { @@ -486,13 +488,13 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe } } - private static class MyIndex extends MapReduceIndex { - public MyIndex(final IndexStorage storage) { + private static class MyIndex extends MapReduceIndex { + public MyIndex(final IndexStorage storage) { super(null, null, storage); } @Override - public void updateWithMap(final int inputId, @NotNull final Map newData, @NotNull Callable> oldKeysGetter) throws StorageException { + public void updateWithMap(final int inputId, @NotNull final Map newData, @NotNull Callable> oldKeysGetter) throws StorageException { super.updateWithMap(inputId, newData, oldKeysGetter); } } diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java index cfb2be18ee98..547f47a6f437 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java @@ -201,21 +201,21 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi return new MyIndex(indexId, storage, getIndexer()); } - private static void updateStubIndices(@NotNull final Collection indexKeys, final int inputId, @NotNull final Map> oldStubTree, @NotNull final Map> newStubTree) { + private static void updateStubIndices(@NotNull final Collection indexKeys, final int inputId, @NotNull final Map> oldStubTree, @NotNull final Map> newStubTree) { final StubIndexImpl stubIndex = (StubIndexImpl)StubIndex.getInstance(); for (StubIndexKey key : indexKeys) { - final Map oldMap = oldStubTree.get(key); - final Map newMap = newStubTree.get(key); + final Map oldMap = oldStubTree.get(key); + final Map newMap = newStubTree.get(key); - final Map _oldMap = oldMap != null ? oldMap : Collections.emptyMap(); - final Map _newMap = newMap != null ? newMap : Collections.emptyMap(); + final Map _oldMap = oldMap != null ? oldMap : Collections.emptyMap(); + final Map _newMap = newMap != null ? newMap : Collections.emptyMap(); stubIndex.updateIndex(key, inputId, _oldMap, _newMap); } } @NotNull - private static Collection getAffectedIndices(@NotNull final Map> oldStubTree, @NotNull final Map> newStubTree) { + private static Collection getAffectedIndices(@NotNull final Map> oldStubTree, @NotNull final Map> newStubTree) { Set allIndices = new HashSet(); allIndices.addAll(oldStubTree.keySet()); allIndices.addAll(newStubTree.keySet()); @@ -254,7 +254,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi throws StorageException { checkNameStorage(); - final Map> newStubTree = getStubTree(newData); + final Map> newStubTree = getStubTree(newData); final StubIndexImpl stubIndex = getStubIndex(); final Collection allStubIndices = stubIndex.getAllStubIndexKeys(); @@ -268,7 +268,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi getWriteLock().lock(); final Map oldData = readOldData(inputId); - final Map> oldStubTree = getStubTree(oldData); + final Map> oldStubTree = getStubTree(oldData); super.updateWithMap(inputId, newData, oldKeysGetter); @@ -302,8 +302,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi } } - private static Map> getStubTree(@NotNull final Map data) { - final Map> stubTree; + private static Map> getStubTree(@NotNull final Map data) { + final Map> stubTree; if (!data.isEmpty()) { final SerializedStubTree stub = data.values().iterator().next(); stubTree = new StubTree((PsiFileStub)stub.getStub(true), false).indexStubTree(); From 9ab8ca5d0631e8bcf4d9b4c347c2b946d8e571d5 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 30 May 2012 19:48:16 +0400 Subject: [PATCH 025/239] extract constants --- .../src/org/jetbrains/android/util/AndroidCommonUtils.java | 2 ++ .../jps/android/AndroidSourceGeneratingBuilder.java | 3 +-- .../compiler/AndroidBuildConfigGeneratingCompiler.java | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java b/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java index 432be8fbea6d..6c90602ad3d3 100644 --- a/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java +++ b/plugins/android/common/src/org/jetbrains/android/util/AndroidCommonUtils.java @@ -88,6 +88,8 @@ public class AndroidCommonUtils { {"JUnit", "TestNG", "ScalaTestRunConfiguration", "SpecsRunConfiguration", "Specs2RunConfiguration"}; @NonNls public static final String ANNOTATIONS_JAR_RELATIVE_PATH = "/tools/support/annotations.jar"; + @NonNls public static final String PACKAGE_MANIFEST_ATTRIBUTE = "package"; + private AndroidCommonUtils() { } diff --git a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java index 8f38c85b047b..7d1cb001b210 100644 --- a/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java +++ b/plugins/android/jps-plugin/src/org/jetbrains/jps/android/AndroidSourceGeneratingBuilder.java @@ -49,7 +49,6 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { @NonNls private static final String AIDL_EXTENSION = "aidl"; @NonNls private static final String RENDERSCRIPT_EXTENSION = "rs"; @NonNls private static final String MANIFEST_TAG = "manifest"; - @NonNls private static final String PACKAGE_MANIFEST_ATTRIBUTE = "package"; @NonNls private static final String PERMISSION_TAG = "permission"; @NonNls private static final String PERMISSION_GROUP_TAG = "permission-group"; @NonNls private static final String NAME_ATTRIBUTE = "name"; @@ -751,7 +750,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder { @Override public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception { - if (value != null && PACKAGE_MANIFEST_ATTRIBUTE.equals(key)) { + if (value != null && AndroidCommonUtils.PACKAGE_MANIFEST_ATTRIBUTE.equals(key)) { packageName.set(value.trim()); } } diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidBuildConfigGeneratingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidBuildConfigGeneratingCompiler.java index 98a8c3319a14..20a79be60a6c 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidBuildConfigGeneratingCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidBuildConfigGeneratingCompiler.java @@ -14,6 +14,7 @@ import com.intellij.util.xml.NanoXmlUtil; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.android.util.AndroidCommonUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,6 +29,7 @@ import java.util.List; */ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCompiler { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidBuildConfigGeneratingCompiler"); + private static final String MANIFEST_LOCATION = NanoXmlUtil.createLocation("manifest"); @Nullable @Override @@ -126,7 +128,8 @@ public class AndroidBuildConfigGeneratingCompiler implements SourceGeneratingCom throws Exception { super.addAttribute(key, nsPrefix, nsURI, value, type); - if ("package".equals(key) && NanoXmlUtil.createLocation("manifest").equals(getLocation())) { + if (AndroidCommonUtils.PACKAGE_MANIFEST_ATTRIBUTE.equals(key) && + MANIFEST_LOCATION.equals(getLocation())) { packageNameRef.set(value); stop(); } From 53643aab1c895b833d3187f45a9c575a32c817ea Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 31 May 2012 18:46:29 +0400 Subject: [PATCH 026/239] new api for android list quick fixes: they should behave correctly in ui designer --- .../designer/inspection/ErrorAnalyzer.java | 4 +- .../lint/AddMissingPrefixQuickFix.java | 18 ++--- .../lint/AndroidLintExternalAnnotator.java | 4 +- .../lint/AndroidLintInspectionBase.java | 4 +- .../inspections/lint/AndroidLintQuickFix.java | 6 +- .../lint/AndroidQuickfixContexts.java | 75 +++++++++++++++++++ .../inspections/lint/ConvertToDpQuickFix.java | 23 +++--- .../lint/InefficientWeightQuickFix.java | 8 +- .../lint/RemoveAttributeQuickFix.java | 8 +- .../lint/RemoveUselessViewQuickFix.java | 8 +- .../lint/SetAttributeQuickFix.java | 61 +++++++++++++-- .../lint/SetScrollViewSizeQuickFix.java | 8 +- .../inspections/lint/TypographyQuickFix.java | 12 +-- 13 files changed, 180 insertions(+), 59 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/AndroidQuickfixContexts.java diff --git a/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java b/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java index 3afda61c8823..a0dd4b11d039 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java +++ b/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java @@ -84,11 +84,11 @@ public final class ErrorAnalyzer { List designerFixes = errorInfo.getQuickFixes(); for (final AndroidLintQuickFix fix : inspection.public_getQuickFixes(message)) { - if (fix.isApplicable(startElement, endElement, false)) { + if (fix.isApplicable(startElement, endElement, AndroidQuickfixContexts.DesignerContext.TYPE)) { designerFixes.add(new QuickFix(fix.getName(), AbstractQuickFixManager.ICON) { @Override public void run() { - fix.apply(startElement, endElement, null); + fix.apply(startElement, endElement, AndroidQuickfixContexts.DesignerContext.getInstance()); } }); } diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java index 67b4c390ad08..d8864cc147bc 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java @@ -2,7 +2,6 @@ package org.jetbrains.android.inspections.lint; import com.android.sdklib.SdkConstants; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; @@ -12,7 +11,6 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.xml.XmlExtension; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.Collections; @@ -21,14 +19,14 @@ import java.util.Collections; */ class AddMissingPrefixQuickFix implements AndroidLintQuickFix { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.AddMissingPrefixQuickFix"); - + @Override - public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context) { final XmlAttribute attribute = PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class, false); if (attribute == null) { return; } - + final XmlTag tag = attribute.getParent(); if (tag == null) { LOG.debug("tag is null"); @@ -40,17 +38,17 @@ class AddMissingPrefixQuickFix implements AndroidLintQuickFix { if (androidNsPrefix == null) { final PsiFile file = tag.getContainingFile(); final XmlExtension extension = XmlExtension.getExtension(file); - + if (extension == null) { LOG.debug("Cannot get XmlExtension for file + " + file); return; } - + if (!(file instanceof XmlFile)) { LOG.debug(file + " is not XmlFile"); return; } - + final XmlFile xmlFile = (XmlFile)file; final String defaultPrefix = "android"; extension.insertNamespaceDeclaration(xmlFile, null, Collections.singleton(SdkConstants.NS_RESOURCES), defaultPrefix, null); @@ -60,7 +58,9 @@ class AddMissingPrefixQuickFix implements AndroidLintQuickFix { } @Override - public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + public boolean isApplicable(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull AndroidQuickfixContexts.ContextType contextType) { return PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class, false) != null; } diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java index 6a5b179b671b..87520d3de2b0 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java @@ -167,7 +167,7 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator 0) { + return Messages.showEditableChooseDialog(message, title, Messages.getQuestionIcon(), variants, variants[0], null); + } + } + } + } + } + return Messages.showInputDialog(context.getProject(), message, title, Messages.getQuestionIcon()); + } + @Override - public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + public boolean isApplicable(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull AndroidQuickfixContexts.ContextType contextType) { + if (myValue == null && contextType == AndroidQuickfixContexts.BatchContext.TYPE) { + return false; + } final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class, false); if (tag == null) { return false; } - return tag.getAttribute(myAttributeName, SdkConstants.NS_RESOURCES) == null; + return tag.getAttribute(myAttributeName, SdkConstants.NS_RESOURCES) == null; } } diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java index 336bb9a11f61..d39332910c63 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java @@ -2,20 +2,18 @@ package org.jetbrains.android.inspections.lint; import com.android.sdklib.SdkConstants; import com.android.tools.lint.detector.api.LintConstants; -import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlTag; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * @author Eugene.Kudelevsky */ class SetScrollViewSizeQuickFix implements AndroidLintQuickFix { @Override - public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context) { final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); if (tag == null) { return; @@ -34,7 +32,9 @@ class SetScrollViewSizeQuickFix implements AndroidLintQuickFix { } @Override - public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + public boolean isApplicable(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull AndroidQuickfixContexts.ContextType contextType) { final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); if (tag == null) { return false; diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java index a290b68ee61d..52091bf9248a 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java @@ -3,14 +3,12 @@ package org.jetbrains.android.inspections.lint; import com.android.tools.lint.checks.TypographyDetector; import com.android.tools.lint.detector.api.Issue; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlTag; import com.intellij.psi.xml.XmlText; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -27,7 +25,7 @@ class TypographyQuickFix implements AndroidLintQuickFix { } @Override - public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context) { final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); if (tag == null) { return; @@ -44,11 +42,11 @@ class TypographyQuickFix implements AndroidLintQuickFix { for (TypographyDetector.ReplaceEdit edit : edits) { String with = edit.replaceWith; - + if (ApplicationManager.getApplication().isUnitTestMode()) { with = with.replace('\u2013', '~').replace('\u2018', '{').replace('\u2019', '}'); } - + builder.replace(edit.offset, edit.offset + edit.length, with); } @@ -62,7 +60,9 @@ class TypographyQuickFix implements AndroidLintQuickFix { } @Override - public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + public boolean isApplicable(@NotNull PsiElement startElement, + @NotNull PsiElement endElement, + @NotNull AndroidQuickfixContexts.ContextType contextType) { return PsiTreeUtil.getParentOfType(startElement, XmlTag.class) != null; } From 6e420869b419e9a72ea24d64d415a439911a8a4d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 31 May 2012 16:50:06 +0200 Subject: [PATCH 027/239] IDEA-85612 Edit Breakpoint Popup: Editing condition in '...' dialog doesn't saves the expression --- .../platform-impl/src/com/intellij/ui/BalloonImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java index 2958e9668b5e..50d9210c4508 100644 --- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.impl.ShadowBorderPainter; @@ -90,7 +91,7 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { final boolean insideBalloon = isInsideBalloon(me); if (myHideOnMouse && id == MOUSE_PRESSED) { - if (!insideBalloon) { + if (!insideBalloon && !hasModalDialog(me)) { hide(); } return; @@ -132,6 +133,12 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui { } } }; + + private static boolean hasModalDialog(MouseEvent e) { + final DialogWrapper dialog = DialogWrapper.findInstance(e.getComponent()); + return dialog != null && dialog.isModal(); + } + private final long myFadeoutTime; private Dimension myDefaultPrefSize; private final ActionListener myClickHandler; From 1b5cea2314cd4d1f52d6a4bd813d436148f135fe Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 31 May 2012 19:00:45 +0400 Subject: [PATCH 028/239] refactor: remove public_getQuickFixes, make getQuickFixes public --- .../designer/inspection/ErrorAnalyzer.java | 2 +- .../lint/AndroidLintInspectionBase.java | 7 +----- .../AndroidLintInspectionToolProvider.java | 22 +++++++++---------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java b/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java index a0dd4b11d039..92f514d700a3 100644 --- a/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java +++ b/plugins/android-designer/src/com/intellij/android/designer/inspection/ErrorAnalyzer.java @@ -83,7 +83,7 @@ public final class ErrorAnalyzer { List designerFixes = errorInfo.getQuickFixes(); - for (final AndroidLintQuickFix fix : inspection.public_getQuickFixes(message)) { + for (final AndroidLintQuickFix fix : inspection.getQuickFixes(message)) { if (fix.isApplicable(startElement, endElement, AndroidQuickfixContexts.DesignerContext.TYPE)) { designerFixes.add(new QuickFix(fix.getName(), AbstractQuickFixManager.ICON) { @Override diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java index a427a0d860de..7a5b3f0af14f 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java @@ -65,15 +65,10 @@ public abstract class AndroidLintInspectionBase extends GlobalInspectionTool imp } @NotNull - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return AndroidLintQuickFix.EMPTY_ARRAY; } - @NotNull - public AndroidLintQuickFix[] public_getQuickFixes(@NotNull String message) { - return getQuickFixes(message); - } - @NotNull public IntentionAction[] getIntentions(@NotNull PsiElement startElement, @NotNull PsiElement endElement) { return IntentionAction.EMPTY_ARRAY; diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java index 855510204e91..dca31689700c 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java @@ -245,7 +245,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider } @NotNull - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{ new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.content.description"), LintConstants.ATTR_CONTENT_DESCRIPTION, null) @@ -381,7 +381,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{new AddMissingPrefixQuickFix()}; } } @@ -417,7 +417,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{ new InefficientWeightQuickFix() }; @@ -437,7 +437,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{ new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.set.baseline.attribute"), LintConstants.ATTR_BASELINE_ALIGNED, "false") @@ -482,7 +482,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{new RemoveAttributeQuickFix()}; } } @@ -506,7 +506,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{new ConvertToDpQuickFix()}; } } @@ -518,7 +518,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{new SetScrollViewSizeQuickFix()}; } } @@ -530,7 +530,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{ new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.permission.attribute"), LintConstants.ATTR_PERMISSION, null) @@ -563,7 +563,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{ new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.input.type.attribute"), LintConstants.ATTR_INPUT_TYPE, null) @@ -636,7 +636,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[]{new RemoveUselessViewQuickFix(myIssue)}; } } @@ -648,7 +648,7 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider @NotNull @Override - protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + public AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { return new AndroidLintQuickFix[] {new TypographyQuickFix(myIssue, message)}; } } From 970ab7b14b6f2bdf4c0b6901cdc7c57e23a7ed88 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 31 May 2012 19:03:31 +0400 Subject: [PATCH 029/239] cosmetics: capitalize title --- .../android/inspections/lint/SetAttributeQuickFix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java index e4ad95f2f982..b478c1e9024b 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java @@ -82,7 +82,7 @@ class SetAttributeQuickFix implements AndroidLintQuickFix { private String askForAttributeValue(@NotNull PsiElement context) { final AndroidFacet facet = AndroidFacet.getInstance(context); final String message = "Specify value of attribute '" + myAttributeName + "'"; - final String title = "Set attribute value"; + final String title = "Set Attribute Value"; if (facet != null) { final SystemResourceManager srm = facet.getSystemResourceManager(); From 31a757336e96ea95d11e0fda6c861658edad14f5 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 31 May 2012 19:18:38 +0400 Subject: [PATCH 030/239] IDEA-85741 subversion integration autodetection broken for 1.7 working copies --- .../openapi/vcs/impl/VcsDescriptor.java | 42 +++++++++++++--- .../VcsMappingConfigurationDialog.java | 50 ++++++++++++++----- .../com/intellij/openapi/vcs/impl/VcsEP.java | 4 +- plugins/svn4idea/src/META-INF/plugin.xml | 2 +- 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsDescriptor.java b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsDescriptor.java index aee403b937d9..56167f373ad0 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsDescriptor.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/VcsDescriptor.java @@ -15,31 +15,57 @@ */ package com.intellij.openapi.vcs.impl; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vfs.VirtualFile; public class VcsDescriptor implements Comparable { private final String myName; + private final boolean myCrawlUpToCheckUnderVcs; private final String myDisplayName; private final String myAdministrativePattern; private boolean myIsNone; - public VcsDescriptor(String administrativePattern, String displayName, String name) { + public VcsDescriptor(String administrativePattern, String displayName, String name, boolean crawlUpToCheckUnderVcs) { myAdministrativePattern = administrativePattern; myDisplayName = displayName; myName = name; + myCrawlUpToCheckUnderVcs = crawlUpToCheckUnderVcs; } public boolean probablyUnderVcs(final VirtualFile file) { if (file == null || (! file.isDirectory()) || (! file.isValid())) return false; if (myAdministrativePattern == null) return false; - final String[] patterns = myAdministrativePattern.split(","); - for (String pattern : patterns) { - final VirtualFile child = file.findChild(pattern.trim()); - if (child != null) return true; - } - return false; + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + if (checkFileForBeingAdministrative(file)) return true; + if (myCrawlUpToCheckUnderVcs) { + VirtualFile current = file.getParent(); + while (current != null) { + if (checkFileForBeingAdministrative(current)) return true; + current = current.getParent(); + } + } + return false; + } + }); + } + + private boolean checkFileForBeingAdministrative(final VirtualFile file) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + final String[] patterns = myAdministrativePattern.split(","); + for (String pattern : patterns) { + final VirtualFile child = file.findChild(pattern.trim()); + if (child != null) return true; + } + return false; + } + }); } public String getDisplayName() { @@ -72,7 +98,7 @@ public class VcsDescriptor implements Comparable { } public static VcsDescriptor createFictive() { - final VcsDescriptor vcsDescriptor = new VcsDescriptor(null, VcsBundle.message("none.vcs.presentation"), null); + final VcsDescriptor vcsDescriptor = new VcsDescriptor(null, VcsBundle.message("none.vcs.presentation"), null, false); vcsDescriptor.myIsNone = true; return vcsDescriptor; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsMappingConfigurationDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsMappingConfigurationDialog.java index 3a06bebec303..5d58c8b8e928 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsMappingConfigurationDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsMappingConfigurationDialog.java @@ -20,6 +20,8 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; import com.intellij.openapi.util.io.FileUtil; @@ -31,6 +33,8 @@ import com.intellij.openapi.vcs.impl.DefaultVcsRootPolicy; import com.intellij.openapi.vcs.impl.VcsDescriptor; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBLabel; +import com.intellij.util.continuation.ModalityIgnorantBackgroundableTask; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -197,20 +201,40 @@ public class VcsMappingConfigurationDialog extends DialogWrapper { super.onFileChoosen(chosenFile); final VcsDescriptor wrapper = (VcsDescriptor) myVCSComboBox.getSelectedItem(); if (oldText.length() == 0 && (wrapper == null || wrapper.isNone())) { - VcsDescriptor probableVcs = null; - for(VcsDescriptor vcs: myVcses.values()) { - if (vcs.probablyUnderVcs(chosenFile)) { - if (probableVcs != null) { - probableVcs = null; - break; + final ModalityIgnorantBackgroundableTask task = + new ModalityIgnorantBackgroundableTask(myProject, "Looking for VCS administrative area, false") { + VcsDescriptor probableVcs = null; + + @Override + protected void doInAwtIfFail(Exception e) { } - probableVcs = vcs; - } - } - if (probableVcs != null) { - // todo none - myVCSComboBox.setSelectedItem(probableVcs); - } + + @Override + protected void doInAwtIfCancel() { + } + + @Override + protected void doInAwtIfSuccess() { + if (probableVcs != null) { + // todo none + myVCSComboBox.setSelectedItem(probableVcs); + } + } + + @Override + protected void runImpl(@NotNull ProgressIndicator indicator) { + for (VcsDescriptor vcs : myVcses.values()) { + if (vcs.probablyUnderVcs(chosenFile)) { + if (probableVcs != null) { + probableVcs = null; + break; + } + probableVcs = vcs; + } + } + } + }; + ProgressManager.getInstance().run(task); } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsEP.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsEP.java index 775947e8592a..7eda8accaa93 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsEP.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsEP.java @@ -43,6 +43,8 @@ public class VcsEP extends AbstractExtensionPointBean { public String displayName; @Attribute("administrativeAreaName") public String administrativeAreaName; + @Attribute("crawlUpToCheckUnderVcs") + public boolean crawlUpToCheckUnderVcs; private AbstractVcs myVcs; @@ -69,6 +71,6 @@ public class VcsEP extends AbstractExtensionPointBean { } public VcsDescriptor createDescriptor() { - return new VcsDescriptor(administrativeAreaName, displayName, name); + return new VcsDescriptor(administrativeAreaName, displayName, name, crawlUpToCheckUnderVcs); } } diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml index a9b27e678deb..12bde03814e6 100644 --- a/plugins/svn4idea/src/META-INF/plugin.xml +++ b/plugins/svn4idea/src/META-INF/plugin.xml @@ -132,7 +132,7 @@ - + From e11f69ee842fe5b38df2229d81eb944c970419e8 Mon Sep 17 00:00:00 2001 From: Evgeny Zakrevsky Date: Thu, 31 May 2012 19:33:45 +0400 Subject: [PATCH 031/239] revert fixing exception --- .../platform-impl/src/com/intellij/ide/IdeRepaintManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java index 694a00782a9c..bb2cf498987c 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java @@ -44,7 +44,6 @@ public class IdeRepaintManager extends RepaintManager { WeakReference myLastComponent; public Image getVolatileOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) { - if (proposedWidth <= 0 || proposedHeight <= 0) return null; final Image buffer = super.getVolatileOffscreenBuffer(c, proposedWidth, proposedHeight); clearLeakyImages(false); // DisplayChangedListener might be unavailable return buffer; From 9a0587b2ad4ed85926c4022789e231b153f8a573 Mon Sep 17 00:00:00 2001 From: Danila Ponomarenko Date: Wed, 30 May 2012 19:35:29 +0400 Subject: [PATCH 032/239] inner -> nested --- .../platform-resources-en/src/messages/UsageView.properties | 2 +- .../usageView/src/com/intellij/usages/impl/rules/UsageType.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-resources-en/src/messages/UsageView.properties b/platform/platform-resources-en/src/messages/UsageView.properties index a8333adb3c88..dab1be4932a9 100644 --- a/platform/platform-resources-en/src/messages/UsageView.properties +++ b/platform/platform-resources-en/src/messages/UsageView.properties @@ -52,7 +52,7 @@ usage.target.xml.tag.of.file={0} of file {1} usage.target.package.in.directory={0} (in {1}) usage.target.exception=Exception usage.type.new=New instance creation -usage.type.new.inner=New inner class instance creation +usage.type.new.nested=New nested class instance creation usage.type.new.anonymous=New anonymous inheritor creation usage.type.new.array=New array creation usage.type.annotation=Annotation diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java index 43905dd67b2e..698bd075f093 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java @@ -31,7 +31,7 @@ public final class UsageType { public static final UsageType CLASS_CATCH_CLAUSE_PARAMETER_DECLARATION = new UsageType(UsageViewBundle.message("usage.type.catch.declaration")); public static final UsageType CLASS_METHOD_RETURN_TYPE = new UsageType(UsageViewBundle.message("usage.type.return")); public static final UsageType CLASS_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new")); - public static final UsageType CLASS_INNER_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new.inner")); + public static final UsageType CLASS_NESTED_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new.nested")); public static final UsageType CLASS_ANONYMOUS_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new.anonymous")); public static final UsageType CLASS_NEW_ARRAY = new UsageType(UsageViewBundle.message("usage.type.new.array")); public static final UsageType ANNOTATION = new UsageType(UsageViewBundle.message("usage.type.annotation")); From 4eabf0d145238112b6028036d990759d0a4f0bb3 Mon Sep 17 00:00:00 2001 From: Danila Ponomarenko Date: Wed, 30 May 2012 21:20:44 +0400 Subject: [PATCH 033/239] IDEA-85626 "Field declaration" usage type group mixes together fields of class and fields of its inner classes fixed --- .../usages/impl/rules/JavaUsageTypeProvider.java | 10 ++++++---- .../src/messages/UsageView.properties | 2 +- .../src/com/intellij/usages/impl/rules/UsageType.java | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java index cce007268945..7cdf805178d0 100644 --- a/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java +++ b/java/java-impl/src/com/intellij/usages/impl/rules/JavaUsageTypeProvider.java @@ -157,6 +157,11 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx { @Nullable private static UsageType getClassUsageType(@NotNull PsiElement element, @NotNull UsageTarget[] targets) { + final PsiJavaCodeReferenceElement codeReference = PsiTreeUtil.getParentOfType(element, PsiJavaCodeReferenceElement.class); + if(codeReference != null && isNestedClassOf(codeReference,targets)){ + return UsageType.CLASS_NESTED_CLASS_ACCESS; + } + if (element.getParent() instanceof PsiAnnotation && element == ((PsiAnnotation)element.getParent()).getNameReferenceElement()) { return UsageType.ANNOTATION; @@ -224,9 +229,6 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx { if (isAnonymousClassOf(psiNewExpression.getAnonymousClass(), targets)) { return UsageType.CLASS_ANONYMOUS_NEW_OPERATOR; } - if (isInnerClassOf(classReference, targets)) { - return UsageType.CLASS_INNER_NEW_OPERATOR; - } if (isNewArrayCreation(psiNewExpression)) { return UsageType.CLASS_NEW_ARRAY; } @@ -249,7 +251,7 @@ public class JavaUsageTypeProvider implements UsageTypeProviderEx { return qualifiesToTargetClasses(anonymousClass.getBaseClassReference(), targets); } - private static boolean isInnerClassOf(PsiJavaCodeReferenceElement classReference, @NotNull UsageTarget[] targets) { + private static boolean isNestedClassOf(PsiJavaCodeReferenceElement classReference, @NotNull UsageTarget[] targets) { final PsiElement qualifier = classReference.getQualifier(); if (qualifier instanceof PsiJavaCodeReferenceElement) { return qualifiesToTargetClasses((PsiJavaCodeReferenceElement)qualifier, targets); diff --git a/platform/platform-resources-en/src/messages/UsageView.properties b/platform/platform-resources-en/src/messages/UsageView.properties index dab1be4932a9..8a0fb1290ae6 100644 --- a/platform/platform-resources-en/src/messages/UsageView.properties +++ b/platform/platform-resources-en/src/messages/UsageView.properties @@ -33,6 +33,7 @@ usage.type.import=Usage in import usage.type.cast.target=Usage in cast target type usage.type.extends=Usage in extends/implements clause usage.type.static.member=Class static member access +usage.type.nested.class=Nested class access usage.type.throws.list=Method throws list usage.type.class.object=Usage in .class usage.type.field.declaration=Field declaration @@ -52,7 +53,6 @@ usage.target.xml.tag.of.file={0} of file {1} usage.target.package.in.directory={0} (in {1}) usage.target.exception=Exception usage.type.new=New instance creation -usage.type.new.nested=New nested class instance creation usage.type.new.anonymous=New anonymous inheritor creation usage.type.new.array=New array creation usage.type.annotation=Annotation diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java index 698bd075f093..c8b2932e014c 100644 --- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java +++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java @@ -23,6 +23,7 @@ public final class UsageType { public static final UsageType CLASS_CAST_TO = new UsageType(UsageViewBundle.message("usage.type.cast.target")); public static final UsageType CLASS_EXTENDS_IMPLEMENTS_LIST = new UsageType(UsageViewBundle.message("usage.type.extends")); public static final UsageType CLASS_STATIC_MEMBER_ACCESS = new UsageType(UsageViewBundle.message("usage.type.static.member")); + public static final UsageType CLASS_NESTED_CLASS_ACCESS = new UsageType(UsageViewBundle.message("usage.type.nested.class")); public static final UsageType CLASS_METHOD_THROWS_LIST = new UsageType(UsageViewBundle.message("usage.type.throws.list")); public static final UsageType CLASS_CLASS_OBJECT_ACCESS = new UsageType(UsageViewBundle.message("usage.type.class.object")); public static final UsageType CLASS_FIELD_DECLARATION = new UsageType(UsageViewBundle.message("usage.type.field.declaration")); @@ -31,7 +32,6 @@ public final class UsageType { public static final UsageType CLASS_CATCH_CLAUSE_PARAMETER_DECLARATION = new UsageType(UsageViewBundle.message("usage.type.catch.declaration")); public static final UsageType CLASS_METHOD_RETURN_TYPE = new UsageType(UsageViewBundle.message("usage.type.return")); public static final UsageType CLASS_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new")); - public static final UsageType CLASS_NESTED_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new.nested")); public static final UsageType CLASS_ANONYMOUS_NEW_OPERATOR = new UsageType(UsageViewBundle.message("usage.type.new.anonymous")); public static final UsageType CLASS_NEW_ARRAY = new UsageType(UsageViewBundle.message("usage.type.new.array")); public static final UsageType ANNOTATION = new UsageType(UsageViewBundle.message("usage.type.annotation")); From 998f5cce1c6dbdaf7ed756e371d1213aede7f502 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 17:28:19 +0200 Subject: [PATCH 034/239] earlier LowMemoryWatcher notifications --- .../jps/incremental/IncProjectBuilder.java | 10 +- .../com/intellij/semantic/SemServiceImpl.java | 5 +- .../openapi/util/LowMemoryWatcher.java | 117 ++++++------------ .../intellij/util/io/PersistentHashMap.java | 4 +- 4 files changed, 42 insertions(+), 94 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 91ccb8ac3f85..8d2e56bc3683 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -1,6 +1,5 @@ package org.jetbrains.jps.incremental; -import com.intellij.openapi.Forceable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.LowMemoryWatcher; import com.intellij.openapi.util.Pair; @@ -93,14 +92,9 @@ public class IncProjectBuilder { public void build(CompileScope scope, final boolean isMake, final boolean isProjectRebuild, boolean forceCleanCaches) throws RebuildRequestedException { - final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(new Forceable() { + final LowMemoryWatcher memWatcher = LowMemoryWatcher.register(new Runnable() { @Override - public boolean isDirty() { - return true; // always perform flush when not enough memory - } - - @Override - public void force() { + public void run() { myProjectDescriptor.dataManager.flush(false); myTimestamps.force(); } diff --git a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java index b386c380a8d9..222e154f132a 100644 --- a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java @@ -89,8 +89,9 @@ public class SemServiceImpl extends SemService{ myInheritors = cacheKeyHierarchy(myProducers.keySet()); - final LowMemoryWatcher watcher = LowMemoryWatcher.register(new LowMemoryWatcher.ForceableAdapter() { - public void force() { + final LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { clearCache(); //System.out.println("SemService cache flushed"); } diff --git a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java index bbdf98350dea..57810812d1d7 100644 --- a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java +++ b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java @@ -15,16 +15,16 @@ */ package com.intellij.openapi.util; -import com.intellij.openapi.Forceable; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.reference.SoftReference; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.WeakList; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import javax.management.Notification; +import javax.management.NotificationEmitter; +import javax.management.NotificationListener; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryNotificationInfo; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryType; /** * @author Eugene Zhuravlev @@ -33,97 +33,50 @@ import java.util.Set; public class LowMemoryWatcher { private static final long MEM_THRESHOLD = 5 /*MB*/ * 1024 * 1024; - public abstract static class ForceableAdapter implements Forceable { - public boolean isDirty() { - return true; - } - } - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.LowMemoryWatcher"); - private static final ReferenceQueue ourRefQueue = new ReferenceQueue(); - @SuppressWarnings({"FieldCanBeLocal"}) - private static SoftReference ourRef; - private static final List> ourInstances = ContainerUtil.createEmptyCOWList(); + private static final WeakList ourInstances = new WeakList(); - private final Forceable myForceable; + private final Runnable myRunnable; static { - final Thread thread = new Thread("LowMemoryWatcher") { - boolean shouldCleanup = false; - public void run() { - updateRef(); - final Set> toRemove = new HashSet>(); - - while (true) { - try { - ourRefQueue.remove(); - updateRef(); - - if (!shouldCleanup) { - final Runtime runtime = Runtime.getRuntime(); - shouldCleanup = runtime.maxMemory() - runtime.totalMemory() <= MEM_THRESHOLD; + for (MemoryPoolMXBean bean : ManagementFactory.getMemoryPoolMXBeans()) { + if (bean.getType() == MemoryType.HEAP && bean.isUsageThresholdSupported()) { + long threshold = bean.getUsage().getMax() - MEM_THRESHOLD; + if (threshold > 0) { + bean.setUsageThreshold(threshold); + bean.setCollectionUsageThreshold(threshold); + } + } + } + ((NotificationEmitter)ManagementFactory.getMemoryMXBean()).addNotificationListener(new NotificationListener() { + public void handleNotification(Notification n, Object hb) { + if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(n.getType()) || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(n.getType())) { + System.out.println(n.getType()); + for (LowMemoryWatcher watcher : ourInstances) { + try { + watcher.myRunnable.run(); } - - for (WeakReference instanceRef : ourInstances) { - final LowMemoryWatcher watcher = instanceRef.get(); - if (watcher == null) { - toRemove.add(instanceRef); - } - else { - if (shouldCleanup) { - try { - watcher.doCleanup(); - } - catch (Throwable e) { - LOG.info(e); - } - } - } + catch (Throwable e) { + LOG.info(e); } - - if (!toRemove.isEmpty()) { - ourInstances.removeAll(toRemove); - toRemove.clear(); - } - - } - catch (InterruptedException ignored) { } } } - }; - thread.setPriority(Thread.NORM_PRIORITY - 1); - thread.setDaemon(true); - thread.start(); + }, null, null); } - public static LowMemoryWatcher register(Forceable forceable) { - return new LowMemoryWatcher(forceable); + public static LowMemoryWatcher register(Runnable runnable) { + return new LowMemoryWatcher(runnable); } - private LowMemoryWatcher(Forceable forceable) { - myForceable = forceable; - updateRef(); - ourInstances.add(new WeakReference(this)); + private LowMemoryWatcher(Runnable runnable) { + myRunnable = runnable; + ourInstances.add(this); } public void stop() { - for (WeakReference ref : ourInstances) { - if (ref.get() == this) { - ourInstances.remove(ref); - break; - } - } + ourInstances.remove(this); } - private void doCleanup() { - if (myForceable.isDirty()) { - myForceable.force(); - } - } - - private static void updateRef() { - ourRef = new SoftReference(new Object(), ourRefQueue); - } } diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java index 61daaf1f6147..196983d4bfae 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java @@ -128,9 +128,9 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< return myCanReEnumerate ? size + POSITIVE_VALUE_SHIFT < Integer.MAX_VALUE: false; } - private final LowMemoryWatcher myAppendCacheFlusher = LowMemoryWatcher.register(new LowMemoryWatcher.ForceableAdapter() { + private final LowMemoryWatcher myAppendCacheFlusher = LowMemoryWatcher.register(new Runnable() { @Override - public void force() { + public void run() { //System.out.println("Flushing caches: " + myFile.getPath()); dropMemoryCaches(); } From 8252e9dc727004efc8a89d27d59bb57b43026f13 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 17:38:53 +0200 Subject: [PATCH 035/239] SofterReference --- .../com/intellij/util/SofterReference.java | 69 +++++++++++++++++++ .../intellij/util/containers/WeakList.java | 9 +++ 2 files changed, 78 insertions(+) create mode 100644 platform/core-impl/src/com/intellij/util/SofterReference.java diff --git a/platform/core-impl/src/com/intellij/util/SofterReference.java b/platform/core-impl/src/com/intellij/util/SofterReference.java new file mode 100644 index 000000000000..e15ef2ccabff --- /dev/null +++ b/platform/core-impl/src/com/intellij/util/SofterReference.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2012 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.util; + +import com.intellij.openapi.util.LowMemoryWatcher; +import com.intellij.util.containers.WeakList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + +/** + * A reference whose referent may be garbage-collected when there's low free memory, not only when there's none. + * Use for objects which retain lots of memory and whose loss is not very expensive. + * + * @author peter + */ +public class SofterReference { + private volatile Reference myRef; + private static final WeakList ourRegistry = new WeakList(); + + @SuppressWarnings("UnusedDeclaration") private static LowMemoryWatcher ourWatcher = LowMemoryWatcher.register(new Runnable() { + @Override + public void run() { + System.out.println("SofterReference.run: " + ourRegistry.size()); + for (SofterReference reference : ourRegistry.copyAndClear()) { + reference.weaken(); + } + } + }); + + public SofterReference(@NotNull T referent) { + ourRegistry.add(this); + myRef = new SoftReference(referent); + } + + private void weaken() { + T o = myRef.get(); + if (o != null) { + myRef = new WeakReference(o); + } + } + + @Nullable + public T get() { + Reference ref = myRef; + T referent = ref.get(); + if (referent != null && ref instanceof WeakReference) { + ourRegistry.add(this); + myRef = new SoftReference(referent); + } + return referent; + } +} diff --git a/platform/util/src/com/intellij/util/containers/WeakList.java b/platform/util/src/com/intellij/util/containers/WeakList.java index 7fb01f556302..22890840ba33 100644 --- a/platform/util/src/com/intellij/util/containers/WeakList.java +++ b/platform/util/src/com/intellij/util/containers/WeakList.java @@ -102,6 +102,15 @@ public class WeakList extends UnsafeWeakList { } } + public List copyAndClear() { + synchronized (myArray) { + List result = new ArrayList(myArray.size()); + myArray.toStrongCollection(result); + clear(); + return result; + } + } + private class MySyncIterator extends MyIterator { protected void findNext() { synchronized (myArray) { From f2765fe5ef84fdd7fbb6a3e645f93b30c5f0e0a3 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 17:43:31 +0200 Subject: [PATCH 036/239] more responsive find usages: group usages outside EDT --- .../usages/impl/UsageNodeTreeBuilderTest.java | 8 +++++- .../com/intellij/usages/impl/GroupNode.java | 16 ++++++------ .../usages/impl/UsageNodeTreeBuilder.java | 7 ++--- .../intellij/usages/impl/UsageViewImpl.java | 26 +++++++++++-------- .../usages/impl/UsageViewManagerImpl.java | 6 +++-- .../impl/UsageViewTreeModelBuilder.java | 9 ++++++- 6 files changed, 46 insertions(+), 26 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java index 1b3d885fd5c7..1b08e40def90 100644 --- a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageNodeTreeBuilderTest.java @@ -22,6 +22,7 @@ import com.intellij.testFramework.LightPlatformTestCase; import com.intellij.usages.*; import com.intellij.usages.rules.UsageFilteringRule; import com.intellij.usages.rules.UsageGroupingRule; +import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -90,7 +91,12 @@ public class UsageNodeTreeBuilderTest extends LightPlatformTestCase { model.setRoot(rootNode); UsageNodeTreeBuilder usageNodeTreeBuilder = new UsageNodeTreeBuilder(UsageTarget.EMPTY_ARRAY, rules, UsageFilteringRule.EMPTY_ARRAY, rootNode); for (Usage usage : usages) { - usageNodeTreeBuilder.appendUsage(usage); + usageNodeTreeBuilder.appendUsage(usage, new Consumer() { + @Override + public void consume(Runnable runnable) { + runnable.run(); + } + }); UIUtil.dispatchAllInvocationEvents(); } diff --git a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java index fd8a33434717..19ac91ad7627 100644 --- a/platform/usageView/src/com/intellij/usages/impl/GroupNode.java +++ b/platform/usageView/src/com/intellij/usages/impl/GroupNode.java @@ -23,7 +23,7 @@ import com.intellij.usages.UsageGroup; import com.intellij.usages.UsageView; import com.intellij.usages.UsageViewSettings; import com.intellij.usages.rules.MergeableUsage; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.Consumer; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,22 +62,22 @@ public class GroupNode extends Node implements Navigatable, Comparable edtQueue) { synchronized (lock) { GroupNode node = mySubgroupNodes.get(group); if (node == null) { final GroupNode node1 = node = new GroupNode(group, ruleIndex, getBuilder()); mySubgroupNodes.put(group, node); - addNode(node1); + addNode(node1, edtQueue); } return node; } } - void addNode(@NotNull final DefaultMutableTreeNode node) { + void addNode(@NotNull final DefaultMutableTreeNode node, @NotNull Consumer edtQueue) { if (!getBuilder().isDetachedMode()) { - UIUtil.invokeLaterIfNeeded(new Runnable() { + edtQueue.consume(new Runnable() { @Override public void run() { myTreeModel.insertNodeInto(node, GroupNode.this, getNodeInsertionIndex(node)); @@ -102,7 +102,7 @@ public class GroupNode extends Node implements Navigatable, Comparable edtQueue) { final UsageNode node; synchronized (lock) { if (UsageViewSettings.getInstance().isFilterDuplicatedLine()) { @@ -168,7 +168,7 @@ public class GroupNode extends Node implements Navigatable, Comparable edtQueue) { if (!isVisible(usage)) return null; GroupNode lastGroupNode = myRoot; @@ -83,10 +84,10 @@ class UsageNodeTreeBuilder { group = rule.groupUsage(usage); } if (group != null) { - lastGroupNode = lastGroupNode.addGroup(group, i); + lastGroupNode = lastGroupNode.addGroup(group, i, edtQueue); } } - return lastGroupNode.addUsage(usage); + return lastGroupNode.addUsage(usage, edtQueue); } } diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index db8dafac57fb..c0219c6ced28 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -34,7 +34,7 @@ import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.PsiDocumentManager; @@ -47,6 +47,7 @@ import com.intellij.usageView.UsageViewManager; import com.intellij.usages.*; import com.intellij.usages.rules.*; import com.intellij.util.Alarm; +import com.intellij.util.Consumer; import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; @@ -237,10 +238,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra } }); } - myTransferToEDTQueue = new TransferToEDTQueue("Insert usages", new Processor() { + myTransferToEDTQueue = new TransferToEDTQueue("Insert usages", new Processor() { @Override - public boolean process(Usage usage) { - appendUsage(usage); + public boolean process(Runnable runnable) { + runnable.run(); return true; } }, new Condition() { @@ -672,7 +673,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra if (usageCount > UsageLimitUtil.USAGES_LIMIT && tooManyUsages.get() == 0 && tooManyUsages.compareAndSet(0, 1)) { ((UsageViewManagerImpl)usageViewManager).showTooManyUsagesWarning(indicator, waitWhileUserClick, usageCountWithoutDefinition.get()); } - appendUsageLater(usage); + appendUsage(usage); } ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); return indicator == null || !indicator.isCanceled(); @@ -699,10 +700,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra } } - private final TransferToEDTQueue myTransferToEDTQueue; - public void appendUsageLater(@NotNull Usage usage) { - myTransferToEDTQueue.offer(usage); - } + private final TransferToEDTQueue myTransferToEDTQueue; public void drainQueuedUsageNodes() { assert !ApplicationManager.getApplication().isDispatchThread() : Thread.currentThread(); UIUtil.invokeAndWaitIfNeeded(new Runnable() { @@ -718,6 +716,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra doAppendUsage(usage); } + @Nullable public UsageNode doAppendUsage(@NotNull Usage usage) { // invoke in ReadAction to be be sure that usages are not invalidated while the tree is being built ApplicationManager.getApplication().assertReadAccessAllowed(); @@ -725,7 +724,12 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra // because the view is built incrementally, the usage may be already invalid, so need to filter such cases return null; } - UsageNode node = myBuilder.appendUsage(usage); + UsageNode node = myBuilder.appendUsage(usage, new Consumer() { + @Override + public void consume(Runnable runnable) { + myTransferToEDTQueue.offer(runnable); + } + }); myUsageNodes.put(usage, node == null ? NULL_NODE : node); return node; } @@ -934,7 +938,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra final Set readOnlyUsages = getReadOnlyUsagesFiles(); return readOnlyUsages.isEmpty() || - !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtil.toVirtualFileArray(readOnlyUsages)).hasReadonlyFiles(); + !ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(VfsUtilCore.toVirtualFileArray(readOnlyUsages)).hasReadonlyFiles(); } @NotNull diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java index 7c055d4e05dc..403812d40399 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java @@ -282,7 +282,7 @@ public class UsageViewManagerImpl extends UsageViewManager { openView(usageView); Usage firstUsage = myFirstUsage.get(); if (firstUsage != null) { - usageView.appendUsageLater(firstUsage); + usageView.appendUsage(firstUsage); } } else { @@ -308,8 +308,10 @@ public class UsageViewManagerImpl extends UsageViewManager { @Override public void run() { + //long start = System.currentTimeMillis(); searchUsages(); endSearchForUsages(); + //System.out.println("Usage search took " + (System.currentTimeMillis() - start)); } private void searchUsages() { @@ -342,7 +344,7 @@ public class UsageViewManagerImpl extends UsageViewManager { } UsageViewImpl usageView = getUsageView(); if (usageView != null) { - usageView.appendUsageLater(usage); + usageView.appendUsage(usage); } } return indicator == null || !indicator.isCanceled(); diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeModelBuilder.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeModelBuilder.java index 8d2da9c0ce91..450e327cd69c 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeModelBuilder.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeModelBuilder.java @@ -17,6 +17,8 @@ package com.intellij.usages.impl; import com.intellij.usages.UsageTarget; import com.intellij.usages.UsageViewPresentation; +import com.intellij.util.Consumer; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import javax.swing.tree.DefaultMutableTreeNode; @@ -66,7 +68,12 @@ public class UsageViewTreeModelBuilder extends DefaultTreeModel { myTargetsNode.add(targetNode); myTargetNodes[i] = targetNode; } - myRootNode.addNode(myTargetsNode); + myRootNode.addNode(myTargetsNode, new Consumer() { + @Override + public void consume(Runnable runnable) { + UIUtil.invokeLaterIfNeeded(runnable); + } + }); } public UsageNode getFirstUsageNode() { From 10b963783a1b5800dd7f19bda273528af36a287d Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 17:51:22 +0200 Subject: [PATCH 037/239] remove debug printing --- platform/core-impl/src/com/intellij/util/SofterReference.java | 1 - .../util/src/com/intellij/openapi/util/LowMemoryWatcher.java | 1 - 2 files changed, 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/util/SofterReference.java b/platform/core-impl/src/com/intellij/util/SofterReference.java index e15ef2ccabff..feef3ad5fc8d 100644 --- a/platform/core-impl/src/com/intellij/util/SofterReference.java +++ b/platform/core-impl/src/com/intellij/util/SofterReference.java @@ -37,7 +37,6 @@ public class SofterReference { @SuppressWarnings("UnusedDeclaration") private static LowMemoryWatcher ourWatcher = LowMemoryWatcher.register(new Runnable() { @Override public void run() { - System.out.println("SofterReference.run: " + ourRegistry.size()); for (SofterReference reference : ourRegistry.copyAndClear()) { reference.weaken(); } diff --git a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java index 57810812d1d7..d7665efbf492 100644 --- a/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java +++ b/platform/util/src/com/intellij/openapi/util/LowMemoryWatcher.java @@ -52,7 +52,6 @@ public class LowMemoryWatcher { ((NotificationEmitter)ManagementFactory.getMemoryMXBean()).addNotificationListener(new NotificationListener() { public void handleNotification(Notification n, Object hb) { if (MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(n.getType()) || MemoryNotificationInfo.MEMORY_COLLECTION_THRESHOLD_EXCEEDED.equals(n.getType())) { - System.out.println(n.getType()); for (LowMemoryWatcher watcher : ourInstances) { try { watcher.myRunnable.run(); From 0df29523b1085ef1d300b3f39498277bc711ea8f Mon Sep 17 00:00:00 2001 From: Danila Ponomarenko Date: Thu, 31 May 2012 20:07:38 +0400 Subject: [PATCH 038/239] IDEA-86807 Inconsistent treatment of type parameters in widen (ctrl-w) fixed --- .../MethodOrClassSelectioner.java | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java index 9efaa06d5feb..bc8f8951217b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java @@ -19,12 +19,15 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; +import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Collections; import java.util.List; /** - * - */ + * + */ public class MethodOrClassSelectioner extends BasicSelectioner { @Override @@ -69,16 +72,44 @@ public class MethodOrClassSelectioner extends BasicSelectioner { } if (e instanceof PsiClass) { - int start = CodeBlockOrInitializerSelectioner.findOpeningBrace(children); - // in non-Java PsiClasses, there can be no opening brace - if (start != 0) { - int end = CodeBlockOrInitializerSelectioner.findClosingBrace(children, start); - - result.addAll(expandToWholeLine(editorText, new TextRange(start, end))); - } + result.addAll(selectWithTypeParameters((PsiClass)e)); + result.addAll(selectBetweenBracesLines(children, editorText)); } return result; } + + private static Collection selectWithTypeParameters(@NotNull PsiClass psiClass) { + final PsiIdentifier identifier = psiClass.getNameIdentifier(); + final PsiTypeParameterList list = psiClass.getTypeParameterList(); + if (identifier != null && list != null) { + return Collections.singletonList(new TextRange(identifier.getTextRange().getStartOffset(), list.getTextRange().getEndOffset())); + } + return Collections.emptyList(); + } + + private static Collection selectBetweenBracesLines(@NotNull PsiElement[] children, + @NotNull CharSequence editorText) { + int start = CodeBlockOrInitializerSelectioner.findOpeningBrace(children); + // in non-Java PsiClasses, there can be no opening brace + if (start != 0) { + int end = CodeBlockOrInitializerSelectioner.findClosingBrace(children, start); + + return expandToWholeLine(editorText, new TextRange(start, end)); + } + return Collections.emptyList(); + } + + private static Collection selectWithoutDocComment(@NotNull PsiElement[] children, + @NotNull CharSequence editorText) { + int start = CodeBlockOrInitializerSelectioner.findOpeningBrace(children); + // in non-Java PsiClasses, there can be no opening brace + if (start != 0) { + int end = CodeBlockOrInitializerSelectioner.findClosingBrace(children, start); + + return expandToWholeLine(editorText, new TextRange(start, end)); + } + return Collections.emptyList(); + } } From b2219e6e662502da7f1fa3e289a4e8055bc5c922 Mon Sep 17 00:00:00 2001 From: Danila Ponomarenko Date: Thu, 31 May 2012 20:09:56 +0400 Subject: [PATCH 039/239] garbage removed --- .../wordSelection/MethodOrClassSelectioner.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java index bc8f8951217b..d727b850ff20 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/wordSelection/MethodOrClassSelectioner.java @@ -100,16 +100,4 @@ public class MethodOrClassSelectioner extends BasicSelectioner { } return Collections.emptyList(); } - - private static Collection selectWithoutDocComment(@NotNull PsiElement[] children, - @NotNull CharSequence editorText) { - int start = CodeBlockOrInitializerSelectioner.findOpeningBrace(children); - // in non-Java PsiClasses, there can be no opening brace - if (start != 0) { - int end = CodeBlockOrInitializerSelectioner.findClosingBrace(children, start); - - return expandToWholeLine(editorText, new TextRange(start, end)); - } - return Collections.emptyList(); - } } From 6326788d96ceaa53dba40ad3ae938dfe5d47d618 Mon Sep 17 00:00:00 2001 From: Oleg Sukhodolsky Date: Thu, 31 May 2012 19:31:22 +0400 Subject: [PATCH 040/239] Refactoring: IndentationFoldingBuilder should create folds for every node of appropriate type, also we can avoid recursion in this algorithm. --- .../indentation/IndentationFoldingBuilder.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java index 447158cc029f..0b96bcaa68ea 100644 --- a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java +++ b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.LinkedList; import java.util.List; +import java.util.Queue; /** * @author oleg @@ -30,13 +31,18 @@ public abstract class IndentationFoldingBuilder implements FoldingBuilder, DumbA } private void collectDescriptors(@NotNull final ASTNode node, @NotNull final List descriptors) { - final ASTNode[] children = node.getChildren(myTokenSet); - if (children.length > 0) { - if (node.getTreeParent() !=null && node.getTextLength() > 1) { - descriptors.add(new FoldingDescriptor(node, node.getTextRange())); + final Queue toProcess = new LinkedList(); + toProcess.add(node); + while (!toProcess.isEmpty()) { + final ASTNode current = toProcess.remove(); + if (current.getTreeParent() != null + && current.getTextLength() > 1 + && myTokenSet.contains(current.getElementType())) + { + descriptors.add(new FoldingDescriptor(current, current.getTextRange())); } - for (ASTNode child : children) { - collectDescriptors(child, descriptors); + for (ASTNode child = current.getFirstChildNode(); child != null; child = child.getTreeNext()) { + toProcess.add(child); } } } From 1e5ded28e015d8ab28df6bfeb643843826b3117b Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 31 May 2012 20:27:43 +0400 Subject: [PATCH 041/239] don't resolve on EDT just for printing --- .../src/com/intellij/codeEditor/printing/PrintAction.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintAction.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintAction.java index ba85ab8cdb53..a8872ea21b8c 100644 --- a/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintAction.java +++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/PrintAction.java @@ -20,8 +20,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; public class PrintAction extends AnAction implements DumbAware { @@ -42,8 +41,8 @@ public class PrintAction extends AnAction implements DumbAware { public void update(AnActionEvent event){ Presentation presentation = event.getPresentation(); DataContext dataContext = event.getDataContext(); - PsiElement psiElement = LangDataKeys.PSI_ELEMENT.getData(dataContext); - if(psiElement instanceof PsiDirectory) { + VirtualFile file = PlatformDataKeys.VIRTUAL_FILE.getData(dataContext); + if(file != null && file.isDirectory()) { presentation.setEnabled(true); return; } From f93626217d961ca389716f9d31ea2bf177982448 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 31 May 2012 21:25:42 +0400 Subject: [PATCH 042/239] Reference AllIcons' fields from xml, rather than resource files directly --- .../src/CommunityFileTypes.xml | 20 ++-- images/src/META-INF/ImagesPlugin.xml | 10 +- .../internal/UsedIconsListingAction.java | 103 ++++++++++-------- .../openapi/actionSystem/AnAction.java | 13 ++- .../src/FileTypeManager.xml | 12 +- .../src/META-INF/LangExtensions.xml | 8 +- .../src/META-INF/XmlActions.xml | 6 +- .../src/idea/LangActions.xml | 64 +++++------ .../src/idea/PlatformActions.xml | 82 +++++++------- .../src/idea/VcsActions.xml | 62 +++++------ .../com/intellij/openapi/util/IconLoader.java | 19 +++- plugins/ant/src/META-INF/plugin.xml | 2 +- plugins/commander/src/META-INF/plugin.xml | 6 +- .../IconsReferencesContributor.java | 45 +++++++- plugins/git4idea/src/META-INF/plugin.xml | 12 +- plugins/gradle/src/META-INF/plugin.xml | 8 +- plugins/groovy/src/META-INF/plugin.xml | 6 +- plugins/hg4idea/src/META-INF/plugin.xml | 4 +- .../action/HgAbstractGlobalAction.java | 9 +- .../src/org/zmlx/hg4idea/action/HgAction.java | 9 ++ .../org/zmlx/hg4idea/action/HgPullAction.java | 4 + .../org/zmlx/hg4idea/action/HgPushAction.java | 6 +- .../src/main/resources/META-INF/plugin.xml | 24 ++-- plugins/ui-designer/src/META-INF/plugin.xml | 4 +- resources/src/META-INF/IdeaPlugin.xml | 2 +- resources/src/idea/JavaActions.xml | 10 +- resources/src/idea/RichPlatformActions.xml | 22 ++-- 27 files changed, 340 insertions(+), 232 deletions(-) diff --git a/community-resources/src/CommunityFileTypes.xml b/community-resources/src/CommunityFileTypes.xml index 141fb501b114..75f58284f129 100644 --- a/community-resources/src/CommunityFileTypes.xml +++ b/community-resources/src/CommunityFileTypes.xml @@ -7,7 +7,7 @@ extensions="idl" default_extension="idl" binary="false" - icon = "/fileTypes/idl.png"> + icon = "AllIcons.FileTypes.Idl"> @@ -71,7 +71,7 @@ extensions="fx" default_extension="fx" binary="false" - icon = "/fileTypes/custom.png"> + icon = "AllIcons.FileTypes.Custom"> @@ -178,7 +178,7 @@ - + - + - + - + - + - + - + - + - + - + - \ No newline at end of file + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 6080ee552079..34444adf12f5 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -669,13 +669,13 @@ - - - - diff --git a/platform/platform-resources/src/META-INF/XmlActions.xml b/platform/platform-resources/src/META-INF/XmlActions.xml index 68831eccf560..052768e5498e 100644 --- a/platform/platform-resources/src/META-INF/XmlActions.xml +++ b/platform/platform-resources/src/META-INF/XmlActions.xml @@ -1,4 +1,4 @@ - + @@ -62,7 +62,7 @@ - + @@ -74,7 +74,7 @@ + icon="AllIcons.Nodes.PpWeb"> diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 19ccf97be8c8..2b4ee16704f5 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -8,8 +8,8 @@ - - + + @@ -35,7 +35,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -423,7 +423,7 @@ - + @@ -593,7 +593,7 @@ - @@ -610,31 +610,31 @@ - - - - - - - - - - + + + + + + + + + + - + + icon="AllIcons.Debugger.ShowCurrentFrame"/> - + - + @@ -654,15 +654,15 @@ - - + + - + + icon="AllIcons.Debugger.MuteBreakpoints"/> - + @@ -730,22 +730,22 @@ - + + icon="AllIcons.Debugger.RestoreLayout"/> - + - - - + + + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index adc5b44d90e8..7d6faf452ca8 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -107,15 +107,15 @@ - - - + + + - - + + @@ -130,32 +130,32 @@ - + - + - + - + - + @@ -168,14 +168,14 @@ - - + + - - + + - + @@ -184,8 +184,8 @@ - - + + @@ -259,7 +259,7 @@ - + @@ -273,12 +273,12 @@ - - + + - - + + @@ -331,8 +331,8 @@ - - + + @@ -357,7 +357,7 @@ - + @@ -366,7 +366,7 @@ - + @@ -432,9 +432,9 @@ + icon="AllIcons.General.ReadHelp"/> + icon="AllIcons.General.TipsOfTheDay"/> @@ -453,22 +453,22 @@ + icon="AllIcons.Nodes.HomeFolder"/> + icon="AllIcons.Nodes.IdeaProject"/> + icon="AllIcons.Actions.New"/> + icon="AllIcons.Actions.NewFolder"/> + icon="AllIcons.Actions.Delete"/> + icon="AllIcons.Actions.Sync"/> + icon="AllIcons.Actions.ShowHiddens"/> @@ -496,8 +496,8 @@ - - + + @@ -539,9 +539,9 @@ - - - + + + @@ -554,6 +554,6 @@ - + diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml index 546ad5328178..91f17d8d3798 100644 --- a/platform/platform-resources/src/idea/VcsActions.xml +++ b/platform/platform-resources/src/idea/VcsActions.xml @@ -1,9 +1,9 @@ + icon="AllIcons._cvs.ShowAsTree"/> - + @@ -12,7 +12,7 @@ - + + icon="AllIcons.Actions.NextOccurence"/> + icon="AllIcons.Actions.PreviousOccurence"/> @@ -48,7 +48,7 @@ text = "VCS Operations Popup..." description="Context aware popup with list of commonly used VCS actions"/> - + @@ -71,21 +71,21 @@ + icon="AllIcons.Actions.Sync"/> + icon="AllIcons.Actions.Commit"/> + icon="AllIcons.Actions.Rollback"/> + icon="AllIcons.General.Add"/> + icon="AllIcons.Actions.Exclude"/> + icon="AllIcons.Actions.Submit1"/> + icon="AllIcons.Actions.FileStatus"/> + icon="AllIcons.Actions.Diff"/> @@ -98,14 +98,14 @@ + icon="AllIcons.Actions.Cancel"/> + icon="AllIcons.General.Add"> + icon="AllIcons.Actions.Exclude"/> @@ -126,9 +126,9 @@ text="Unshelve..." description="Correct paths where to apply patches and unshelve"/> + icon="AllIcons.Actions.Diff"/> + icon="AllIcons.Actions.CreatePatch"/> + icon="AllIcons.Vcs.Refresh"/> + icon="AllIcons.Ant.Filter"/> + icon="AllIcons.Actions.ShowChangesOnly"/> + icon="AllIcons.Actions.Rollback"/> + icon="AllIcons.Vcs.Remove"/> @@ -160,7 +160,7 @@ + icon="AllIcons.Vcs.Refresh"/> - + - + @@ -121,7 +121,7 @@ - + @@ -142,4 +142,4 @@ - \ No newline at end of file + diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index f71a9c20989f..55b29dccf347 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -1067,10 +1067,10 @@ + icon="AllIcons.General.Remove" text="Remove" description="Remove dynamic element"/> - - + + diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 020691fa5749..46c00acb22ad 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -46,8 +46,8 @@ - - + + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java index 815922ec1c75..8d1b4b53b486 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java @@ -18,13 +18,20 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsImplUtil; import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.util.HgUtil; import org.zmlx.hg4idea.execution.HgCommandException; +import org.zmlx.hg4idea.util.HgUtil; +import javax.swing.*; import java.lang.reflect.InvocationTargetException; import java.util.Collection; abstract class HgAbstractGlobalAction extends AnAction { + protected HgAbstractGlobalAction(Icon icon) { + super(icon); + } + + protected HgAbstractGlobalAction() { + } protected abstract HgGlobalCommandBuilder getHgGlobalCommandBuilder(Project project); private static final Logger LOG = Logger.getInstance(HgAbstractGlobalAction.class.getName()); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java index 7081a6f5b4e9..6ef4a88a02bb 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAction.java @@ -18,10 +18,19 @@ package org.zmlx.hg4idea.action; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; +import javax.swing.*; + /** * @author Kirill Likhodedov */ public abstract class HgAction extends AnAction { + protected HgAction() { + } + + protected HgAction(Icon icon) { + super(icon); + } + @Override public void actionPerformed(AnActionEvent event) { final DataContext dataContext = event.getDataContext(); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java index b8451f14fab7..9d53d02e0279 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPullAction.java @@ -12,6 +12,7 @@ // limitations under the License. package org.zmlx.hg4idea.action; +import com.intellij.icons.AllIcons; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; @@ -23,6 +24,9 @@ import org.zmlx.hg4idea.ui.HgPullDialog; import java.util.Collection; public class HgPullAction extends HgAbstractGlobalAction { + public HgPullAction() { + super(AllIcons.Actions.CheckOut); + } protected HgGlobalCommandBuilder getHgGlobalCommandBuilder(final Project project) { return new HgGlobalCommandBuilder() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java index b55bfc50abf7..1f8e42abfd6f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgPushAction.java @@ -12,12 +12,14 @@ // limitations under the License. package org.zmlx.hg4idea.action; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.icons.AllIcons; import com.intellij.openapi.project.Project; import org.zmlx.hg4idea.HgPusher; public class HgPushAction extends HgAction { - private static final Logger LOG = Logger.getInstance(HgPushAction.class); + public HgPushAction() { + super(AllIcons.Actions.Commit); + } @Override public void execute(final Project project) { diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index 80eae7de882a..1138d95b7553 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -156,12 +156,12 @@ + icon="AllIcons.Actions.Sync"> + icon="AllIcons.Actions.Sync"> + icon="AllIcons.General.Add"> + icon="AllIcons.General.Add"> @@ -225,7 +225,7 @@ class="org.jetbrains.idea.maven.project.actions.RemoveManagedFilesAction" text="Remove Projects" description="Remove selected Maven projects from the project tree" - icon="/general/remove.png"> + icon="AllIcons.General.Remove"> + icon="AllIcons.Actions.Execute"> + icon="AllIcons.Actions.ShowSettings"> + icon="AllIcons.Nodes.ExceptionClass"> @@ -330,13 +330,13 @@ text="Group Modules" description="Group projects according to Maven structure" secondary="true" - icon="/nodes/folder.png"/> + icon="AllIcons.Nodes.Folder"/> + icon="AllIcons.Actions.ShowHiddens"/> + icon="AllIcons.Actions.Preview"/> + icon="AllIcons.Actions.Refresh"/> diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index acb49fac6a1a..a2400794960f 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1254,7 +1254,7 @@ + icon="AllIcons.General.ProjectStructure"> diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index efc76f8b37cd..d6edb106f607 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -94,7 +94,7 @@ - + @@ -105,10 +105,10 @@ - + - + @@ -138,14 +138,14 @@ - + - + diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml index bc88209c38a0..10fa797c9195 100644 --- a/resources/src/idea/RichPlatformActions.xml +++ b/resources/src/idea/RichPlatformActions.xml @@ -29,17 +29,17 @@ + icon="AllIcons.RunConfigurations.RerunFailedTests"/> + icon="AllIcons.Nodes.ModuleClosed"> + icon="AllIcons.Nodes.ModuleClosed"/> @@ -90,7 +90,7 @@ - + @@ -376,17 +376,17 @@ + icon="AllIcons.General.CreateNewProject"/> + icon="AllIcons.General.OpenProject"/> + icon="AllIcons.General.JetbrainsTvIdea"/> + icon="AllIcons.General.PluginManager"/> @@ -403,9 +403,9 @@ - - - + + + From d1cf24b6e7930ef2b9189c2ce22c61e3e5d3e992 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 31 May 2012 14:19:36 +0400 Subject: [PATCH 043/239] search for first class file in all roots to detect language level --- .../psi/impl/JavaPsiImplementationHelperImpl.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java index 3a887e667551..fe729adddc94 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java @@ -142,24 +142,27 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper for (VirtualFile rootFile : files) { final VirtualFile classFile = rootFile.findFileByRelativePath(relativePath); if (classFile != null) { - return getLanguageLevel(classFile); + final PsiJavaFile javaFile = getPsiFileInRoot(classFile); + if (javaFile != null) { + return javaFile.getLanguageLevel(); + } } } + return LanguageLevelProjectExtension.getInstance(myProject).getLanguageLevel(); } return null; } - private LanguageLevel getLanguageLevel(final VirtualFile dirFile) { + @Nullable + private PsiJavaFile getPsiFileInRoot(final VirtualFile dirFile) { final VirtualFile[] children = dirFile.getChildren(); - final LanguageLevel defaultLanguageLevel = LanguageLevelProjectExtension.getInstance(myProject).getLanguageLevel(); for (VirtualFile child : children) { if (StdFileTypes.CLASS.equals(child.getFileType())) { final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(child); - if (psiFile instanceof PsiJavaFile) return ((PsiJavaFile)psiFile).getLanguageLevel(); + if (psiFile instanceof PsiJavaFile) return ((PsiJavaFile)psiFile); } } - - return defaultLanguageLevel; + return null; } @Override From b950ee85623a944fcc9b9b7f0bef764f1d3e87ee Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 31 May 2012 20:13:01 +0400 Subject: [PATCH 044/239] extract method: no need to declare variables after call when expression was extracted --- .../extractMethod/ExtractMethodProcessor.java | 1 + .../VarDeclAfterExpressionExtraction.java | 34 +++++++++++++++++ ...arDeclAfterExpressionExtraction_after.java | 38 +++++++++++++++++++ .../refactoring/ExtractMethodTest.java | 3 ++ 4 files changed, 76 insertions(+) create mode 100644 java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction_after.java diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 41bbe91ca43d..f6895cc4fe35 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -1157,6 +1157,7 @@ public class ExtractMethodProcessor implements MatchProvider { } protected void declareNecessaryVariablesAfterCall(PsiVariable outputVariable) throws IncorrectOperationException { + if (myHasExpressionOutput) return; List usedVariables = myControlFlowWrapper.getUsedVariables(); Collection reassigned = myControlFlowWrapper.getInitializedTwice(); for (PsiVariable variable : usedVariables) { diff --git a/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction.java b/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction.java new file mode 100644 index 000000000000..a757c44cdfc0 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction.java @@ -0,0 +1,34 @@ +class BasicLazyResolveTest { + + + public void test() { + + Object session = new Object() { + +/* + public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(JetClass jetClassOrObject) { + final JetClass jetClass = (JetClass) jetClassOrObject; + return new ClassMemberDeclarationProvider() {*/ + + + /* private List filter(List list, final Class t, final Name name) { + //noinspection unchecked + return (List) Lists.newArrayList(Collections2.filter(list, new Predicate() { + @Override + public boolean apply(D d) { + return t.isInstance(d) && ((JetNamed) d).getNameAsName().equals(name); + } + })); + }*/ + + + /* }; + }*/ + }; + + String packageDescriptor = session.toString(); + + } + + +} diff --git a/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction_after.java b/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction_after.java new file mode 100644 index 000000000000..cb7aeffa679d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/VarDeclAfterExpressionExtraction_after.java @@ -0,0 +1,38 @@ +class BasicLazyResolveTest { + + + public void test() { + + Object session = newMethod(); + + String packageDescriptor = session.toString(); + + } + + private Object newMethod() { + return new Object() { + +/* + public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(JetClass jetClassOrObject) { + final JetClass jetClass = (JetClass) jetClassOrObject; + return new ClassMemberDeclarationProvider() {*/ + + + /* private List filter(List list, final Class t, final Name name) { + //noinspection unchecked + return (List) Lists.newArrayList(Collections2.filter(list, new Predicate() { + @Override + public boolean apply(D d) { + return t.isInstance(d) && ((JetNamed) d).getNameAsName().equals(name); + } + })); + }*/ + + + /* }; + }*/ + }; + } + + +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index fba5f90a20fa..123b3e4bedad 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -194,6 +194,9 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testVarDeclAfterExpressionExtraction() throws Exception { + doTest(); + } public void testFinalParamUsedInsideAnon() throws Exception { CodeStyleSettingsManager.getSettings(getProject()).GENERATE_FINAL_PARAMETERS = false; From 95733028b58bebf2247d4bab4a9fea139be0c820 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 31 May 2012 20:51:38 +0400 Subject: [PATCH 045/239] push down: substitute pushed dependencies (IDEA-86870) --- .../memberPushDown/PushDownProcessor.java | 9 ++++++++- .../refactoring/pushDown/PreserveTypeArgs.java | 6 ++++++ .../refactoring/pushDown/PreserveTypeArgs.java.after | 6 ++++++ .../testData/refactoring/pushDown/SubstTypeArgs.java | 6 ++++++ .../refactoring/pushDown/SubstTypeArgs.java.after | 6 ++++++ .../com/intellij/refactoring/PushDownTest.java | 12 ++++++++++++ 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java create mode 100644 java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java.after create mode 100644 java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java create mode 100644 java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java.after diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java index 543137d65e60..a3a95859fe06 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java @@ -392,8 +392,15 @@ public class PushDownProcessor extends BaseRefactoringProcessor { else if (member instanceof PsiClass) { if (Boolean.FALSE.equals(memberInfo.getOverrides())) { final PsiClass aClass = (PsiClass)memberInfo.getMember(); + PsiClassType classType = null; if (!targetClass.isInheritor(aClass, false)) { - PsiJavaCodeReferenceElement classRef = factory.createClassReferenceElement(aClass); + final PsiClassType[] types = memberInfo.getSourceReferenceList().getReferencedTypes(); + for (PsiClassType type : types) { + if (type.resolve() == aClass) { + classType = (PsiClassType)substitutor.substitute(type); + } + } + PsiJavaCodeReferenceElement classRef = classType != null ? factory.createReferenceElementByType(classType) : factory.createClassReferenceElement(aClass); if (aClass.isInterface()) { targetClass.getImplementsList().add(classRef); } else { diff --git a/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java b/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java new file mode 100644 index 000000000000..dbf4610b3c0b --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java @@ -0,0 +1,6 @@ +import java.util.*; +abstract class Test implements List { +} + +abstract class B extends Test { +} diff --git a/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java.after b/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java.after new file mode 100644 index 000000000000..1e26dd3ef0e2 --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/PreserveTypeArgs.java.after @@ -0,0 +1,6 @@ +import java.util.*; +abstract class Test { +} + +abstract class B extends Test implements List { +} diff --git a/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java b/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java new file mode 100644 index 000000000000..4b90ba60d12d --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java @@ -0,0 +1,6 @@ +import java.util.*; +abstract class Test implements List { +} + +abstract class B extends Test { +} diff --git a/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java.after b/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java.after new file mode 100644 index 000000000000..bee78b91e57c --- /dev/null +++ b/java/java-tests/testData/refactoring/pushDown/SubstTypeArgs.java.after @@ -0,0 +1,6 @@ +import java.util.*; +abstract class Test { +} + +abstract class B extends Test implements List { +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java index 455b87b19e89..04690faf94c4 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PushDownTest.java @@ -120,6 +120,18 @@ public class PushDownTest extends LightRefactoringTestCase { } public void testSameClassInterface() throws Exception { + doTestImplements(); + } + + public void testPreserveTypeArgs() throws Exception { + doTestImplements(); + } + + public void testSubstTypeArgs() throws Exception { + doTestImplements(); + } + + private void doTestImplements() { final String filePath = "/refactoring/pushDown/" + getTestName(false) + ".java"; configureByFile(filePath); From f1b1f669253fcc46673af5695e15e706a9303870 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 31 May 2012 21:19:43 +0400 Subject: [PATCH 046/239] remember configured annotations on ok only (IDEA-86853) --- .../codeInspection/ex/EntryPointsManagerImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java index d7d6d37ee529..a704e3cb204b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/EntryPointsManagerImpl.java @@ -350,7 +350,8 @@ public class EntryPointsManagerImpl implements PersistentStateComponent @Override public void configureAnnotations() { - final JPanel listPanel = SpecialAnnotationsUtil.createSpecialAnnotationsListControl(ADDITIONAL_ANNOTATIONS, "Do not check if annotated by", true); + final ArrayList list = new ArrayList(ADDITIONAL_ANNOTATIONS); + final JPanel listPanel = SpecialAnnotationsUtil.createSpecialAnnotationsListControl(list, "Do not check if annotated by", true); new DialogWrapper(myProject) { { init(); @@ -361,6 +362,13 @@ public class EntryPointsManagerImpl implements PersistentStateComponent protected JComponent createCenterPanel() { return listPanel; } + + @Override + protected void doOKAction() { + ADDITIONAL_ANNOTATIONS.clear(); + ADDITIONAL_ANNOTATIONS.addAll(list); + super.doOKAction(); + } }.show(); } From babdd2a18c1c5de8df9235e2c53a0d5df6fd798b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 31 May 2012 14:01:14 +0400 Subject: [PATCH 047/239] Cleanup --- .../com/intellij/lang/java/parser/ExpressionParser.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index 1e2cebe67217..b65578b6df00 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -62,7 +62,7 @@ public class ExpressionParser { private static final TokenSet ARGS_LIST_END = TokenSet.create(JavaTokenType.RPARENTH, JavaTokenType.RBRACE, JavaTokenType.RBRACKET); private static final TokenSet ARGS_LIST_CONTINUE = TokenSet.create( JavaTokenType.IDENTIFIER, TokenType.BAD_CHARACTER, JavaTokenType.COMMA, JavaTokenType.INTEGER_LITERAL, JavaTokenType.STRING_LITERAL); - private static final TokenSet CONSTRUCTOR_CALL = TokenSet.create(JavaTokenType.THIS_KEYWORD, JavaTokenType.SUPER_KEYWORD); + private static final TokenSet THIS_OR_SUPER = TokenSet.create(JavaTokenType.THIS_KEYWORD, JavaTokenType.SUPER_KEYWORD); public ExpressionParser(DeclarationParser declarationParser, ReferenceParser referenceParser) { myDeclarationParser = declarationParser; @@ -363,8 +363,7 @@ public class ExpressionParser { dotPos.drop(); expr = parseNew(builder, expr); } - else if ((dotTokenType == JavaTokenType.THIS_KEYWORD || dotTokenType == JavaTokenType.SUPER_KEYWORD) && - exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { + else if (THIS_OR_SUPER.contains(dotTokenType) && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) { if (breakPoint == BreakPoint.P2 && builder.getCurrentOffset() == breakOffset) { dotPos.rollbackTo(); startMarker.drop(); @@ -581,13 +580,13 @@ public class ExpressionParser { } tokenType = builder.getTokenType(); - if (!CONSTRUCTOR_CALL.contains(tokenType)) { + if (!THIS_OR_SUPER.contains(tokenType)) { expr.rollbackTo(); return null; } } - if (CONSTRUCTOR_CALL.contains(tokenType)) { + if (THIS_OR_SUPER.contains(tokenType)) { if (expr == null) { expr = builder.mark(); builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST); From cae648dcf0d6cb3e3c72c2293a7b5c16d9783f36 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 31 May 2012 21:39:09 +0400 Subject: [PATCH 048/239] do not recreate directory --- .../org/jetbrains/android/compiler/tools/AndroidApkBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java index 70d180c8bec5..a3fedd4c41e6 100644 --- a/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java +++ b/plugins/android/common/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java @@ -177,7 +177,7 @@ public class AndroidApkBuilder { continue; } - if (!dstDir.mkdirs()) { + if (!dstDir.exists() && !dstDir.mkdirs()) { map.get(ERROR).add("Cannot create directory: " + FileUtil.toSystemDependentName(dstDir.getPath())); continue; } From 3be3a615b5abb387e2e112831dea4189f6e29e46 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 31 May 2012 21:56:04 +0400 Subject: [PATCH 049/239] Yet a bit more icons removed --- platform/icons/src/_cvs/checkOut.png | Bin 539 -> 0 bytes platform/icons/src/_cvs/cvs.png | Bin 537 -> 0 bytes platform/icons/src/_cvs/hideMissing.png | Bin 438 -> 0 bytes platform/icons/src/_cvs/hideUnknown.png | Bin 476 -> 0 bytes platform/icons/src/_cvs/hideUptodate.png | Bin 435 -> 0 bytes platform/icons/src/_cvs/missing.png | Bin 182 -> 0 bytes platform/icons/src/_cvs/testInProgress1.png | Bin 806 -> 0 bytes platform/icons/src/_cvs/testInProgress2.png | Bin 812 -> 0 bytes platform/icons/src/_cvs/testInProgress3.png | Bin 809 -> 0 bytes platform/icons/src/_cvs/testInProgress4.png | Bin 809 -> 0 bytes platform/icons/src/_cvs/testInProgress5.png | Bin 812 -> 0 bytes platform/icons/src/_cvs/testInProgress6.png | Bin 806 -> 0 bytes platform/icons/src/_cvs/testInProgress7.png | Bin 806 -> 0 bytes platform/icons/src/_cvs/testInProgress8.png | Bin 806 -> 0 bytes platform/icons/src/_cvs/unknown.png | Bin 199 -> 0 bytes .../src/{_cvs => actions}/showAsTree.png | Bin .../platform-resources/platform-resources.iml | 1 + .../src/idea/VcsActions.xml | 4 ++-- .../util/src/com/intellij/icons/AllIcons.java | 21 +----------------- .../cvsSupport2/ui/CvsTabbedWindow.java | 2 +- 20 files changed, 5 insertions(+), 23 deletions(-) delete mode 100644 platform/icons/src/_cvs/checkOut.png delete mode 100644 platform/icons/src/_cvs/cvs.png delete mode 100644 platform/icons/src/_cvs/hideMissing.png delete mode 100644 platform/icons/src/_cvs/hideUnknown.png delete mode 100644 platform/icons/src/_cvs/hideUptodate.png delete mode 100644 platform/icons/src/_cvs/missing.png delete mode 100644 platform/icons/src/_cvs/testInProgress1.png delete mode 100644 platform/icons/src/_cvs/testInProgress2.png delete mode 100644 platform/icons/src/_cvs/testInProgress3.png delete mode 100644 platform/icons/src/_cvs/testInProgress4.png delete mode 100644 platform/icons/src/_cvs/testInProgress5.png delete mode 100644 platform/icons/src/_cvs/testInProgress6.png delete mode 100644 platform/icons/src/_cvs/testInProgress7.png delete mode 100644 platform/icons/src/_cvs/testInProgress8.png delete mode 100644 platform/icons/src/_cvs/unknown.png rename platform/icons/src/{_cvs => actions}/showAsTree.png (100%) diff --git a/platform/icons/src/_cvs/checkOut.png b/platform/icons/src/_cvs/checkOut.png deleted file mode 100644 index 0deafaa170fd73931a58dd0326073082b3f0cba4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmV+$0_6RPP)kF#rerhtvGYI&uAjIT#cgPMu^{r&z+H_lE#$XH#FZdLkwX8Hm- zcDSneyu{h)@%!oV`|9%h>ht^S^Zf1f{O__}l6D-Rk+> z>-yj8`QYvQ;q3Y1@A~8K`{eHW=J5JXJJ9Iz`$bBfQ9aR8S&r)S{8L$u?DhOpT8>m& zkM8#U@AdpwT#r{>k47}jxzO;t((&f;`{(id=kokXHqL`__wV-n@b~=i_xFe|J^z{2?!Q(;z0065=L_t&-S7pvc z7Q#RfMbSX;ZsH^acXxMpcisO!ph<@Tyi=olYVZl-uYeoH{Rk)M^t$(%v2d=-c{&<& zZYJf&?b>Y`)p9;}MW7)`i= zgjtpap;}VLKvC3w3H+6WT?K}zw?V8FmlWU;^gy?`7S$b($#~fJ6;@lkR5&^vvRx8w dDi{slh!<9C7T@Y@-tzze002ovPDHLkV1gd0Esy{J diff --git a/platform/icons/src/_cvs/cvs.png b/platform/icons/src/_cvs/cvs.png deleted file mode 100644 index f46a91236a9b07cad20fd7d858c98c9b481664be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 537 zcmV+!0_OdRP)pFGFByaaS)xU@SjdDm+&!Lu4vJVJA3KMLs=4Jv~T6K2KLlWKu&=Mmttp zM<`K)Q9m;EfjwP;NI*JVM=(Kuzi3V=YGFEic0W!+H+g(QK4p?JXrydI9+q`V zOLU@#h(L~eGmnBekdHpik|UO77^9v#qjVU`br0Ez6Rm$h^0gK6yBq466GX}X{rO?A zcMpq(J(F$;lWq#AsXc!tQT^~m{qjTo@>7U{JpTJ! z|NdaTGh~d+u-Hh)++; z&eYuChI?3@aO97=j-su z&ezu4;mXk2?eO#M@bvES^vcoM@bmWZ^Y-%d_1xm=^Y!-h_4nQ3=4#CR_W%F@2Xsfdx%e$`m1x)j<+9QDDrz^4x5c96t@~j0A89Ux<=LSHit4gQ7-&z2hr9W`n gP3tb8QZ5FeH$qtr1hIcqga7~l07*qoM6N<$g0;s0+W-In diff --git a/platform/icons/src/_cvs/hideUnknown.png b/platform/icons/src/_cvs/hideUnknown.png deleted file mode 100644 index ae5728e8192fbee9f8a8b335e91e35da305dbc6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 476 zcmV<20VDp2P)Z#=+QQfK#o6>mTYJpj^-5lR&*Apc%v=lI#^`P%6C-0Jz@?fT;H`sMKZ=kfdO_5APl{POty`27C4(D2ga_q)>Z z)8qHk>iXU5`rhmL-t79| z?D|Amdf@H*;_mvz+4JM?`%GVaOkaKI^84uW{Oa@k>h%1}-u3SG{qObsM_YUF_Wkhp z{qgwy@%jCpvB;*j%E;UFlBUIwA|m$y000JbQchC<>Fe?F@i_-?mjD0&o=HSOR2Wxf z%2f`+P!t5vR|>E0?#12R-P!+oAZaflVKVb`G6?+#r~45WvqXmYG?xI2sn}%L317yi>5PAbcN)DqE SU9<`S0000e;C%KF{R?A*=m-Oc^r&hOvQ@Zi$%;necv*!Jkz`03pG>)re8;Qj9B|MThp^7Q}u z%k12?=E*={XS(XmL1Adl{^8I6;zD6)LSkt|WNX#)<<<1%*7WAr_2xumY({2nuiwHz zUS;0=?ce+$jNIR|f-0001%Nklc_#9U8dVeDv1uyukFr8{=Shu(UkJDHmF=ds0=W2WpU#*!evU1KIqEP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~^BW|Noi! zf-w1lG5Lr(`in67jWzwtsr}Kk|GXss$vpqdT>s5U`F<+@|DONgDPtfPYe!7=~BH2=mr|HerBo?!c;X8fl<{Hi|uuzdWmef+Xf{Iq8LwQBsiS^T?P z{JdZP*lYjUT>sgQ|Jqys-CY0QV*lS{|KN@Pyfgp6Ec%l^`j<%hoKpYJQ~%Cv|Icmz z&~*RNO#jhM|J6_b)lmP}h5C*&|LAi6>8k(ga{udf|LeN{?0Em}y#MXS`F|?~(|K+a#=B)j{mHB!kT3uOMUtf1~VgBQH{_y7h@s9ttAOG&d z|MP_Z^V$FO+5hy~|MlJf`j7wqm;bjS|Nol*|C|5+o&UHW|No!=xh?S5_6}XU6Jt05T0Q#A7C*qW}N^07*qoM6N<$f`})!jsO4v diff --git a/platform/icons/src/_cvs/testInProgress2.png b/platform/icons/src/_cvs/testInProgress2.png deleted file mode 100644 index 7d9b0d03fd7b8cc59fd24a6d42a001db46186b10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 812 zcmV+{1JnG8P) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~w|v|No%* zf-w1lG5`OW{n51k->UxOcmD9^{_&3aek%X}n*aZv|LAf0mq_}YQv04@`=Vz2r#}3u zKK!tJ{IGrevQhlBX8g5k|H)hb%Uu7>N&n7M|ITdx&tw13ZU4}8|ItkU(M|u=Pyf|W z|J7>$*M8k(ga{udf|LeN{?0EW%F#3%(`i?XD zkT?2}IRCpP`G`9IxF7$yE&u%iK|Gqr`z%2jST>sgQ|Jqys+K2z$ zT>sx<|KDW);En&`Z2#hU|Kpke<&OX5uK(t&{JB~DyIlOdU;V$8fp}7fdQg*tQ~&L} z|Lw;A?!*7{g#Yu||Mc1a^xFUR-T(TJ|NfWxdL&s}RR8~*|Nos`T~cLXPx_NS|No)M zXX&5-001*|QchC4Qv1a0MSWAK~xx5V_?7r7`X)%R=IOnezS#DGd?+ozrGYfOPTd_e`|(a!hya>L}Fa1`3D-PwMt|H+Hdg z3y&)h0t%=F^(H!5Sht&{)r1u(0R>ciYa3^K7(3f$q*j+I0tLj1qv}0PbK diff --git a/platform/icons/src/_cvs/testInProgress3.png b/platform/icons/src/_cvs/testInProgress3.png deleted file mode 100644 index 167811a22d9076fafc50e075d922e7adf357ede0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 809 zcmV+^1J?YBP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~J`J{mZHU z|C#^)p81G6`in67jWzm?Gy0G>`F|??(X{@@MgHHa{^NK4@aF#Uj{mkF|Fs5U|ISnY&TRkBWB<=>|Il>*(M8k(ga{udf z`GPR{f-(R9p!$$F`jbBTmq_}YQv04@|GOpsyd(d-B>%iK|Gqr`!7=~BH2=mr|HerB zqGtT3KK!aa{IGoduzmcpQT()K{IzQQxmoQLW|J6|c)oTCOh5y)V|Jhvs*^d9( zTmRaJ|J_{w;En&`Z2#hU|Kpke<&OX5uK(t&{lArWd0~BeTB)XPtf6B6>$?B#y#MXS z|L(*8^MwEN+5hy}|Mc4b_1*vakN^Ic`FbS(|C;~*oB#ivT3l5B|DRf2Rsa8?^vo732lD8DVm)QU<=BDQ-FvY!DGn&9bKE zYQGFuXLYa$vrJ`Qe`iCfPkNGz1V|UJe)k0X{8-B@JC8(dZlHijz{IYC9Ft7r>=F-m zA)tVoe@|$ftz%21MMv8VC7^(cS8ZcVu1UPHReS3!MWBFKa(R7Tgt^U>qDdiX!axBY zL+?6=!f5Mar|Dt3AVZnt5^8!UPc=2278N83b}YMAYIxL4v)N`<8Y~c}a>*J61_xK@ nNprwF!^9`9tSZXSjMe7=6xlIJ5}V@p00000NkvXXu0mjfHYc?) diff --git a/platform/icons/src/_cvs/testInProgress4.png b/platform/icons/src/_cvs/testInProgress4.png deleted file mode 100644 index fec75adf81442cbe8b6a49fbfe2ded63ea478a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 809 zcmV+^1J?YBP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~J`J|GXss z|DO4RG5Lr(`in67jWzm?Gy0G>`j9yN%c=joGylFk|H(Z6$y@)+T>s5U|LAf5|C#^) zn)!k-|GOpsyd(RfX8fl<{Hi|xz%2j4G5^9e|HeB1#z_3IeEhI|{IXH}v}XLZYW%rb z{JUKIykGslm4}mh|FvjL@x|5f7|J6|c)oTCOh5y)V|Jhvs*^d9( zhyUGN|KDQ&-(>&bjsM|n|KfT7o732lD8DVm)QU>Xc_HjBAY!DGn&9df} zs*J$cTy?MrvrOfLiA9a2X#plN5+Gf?`n{8qL%S@!lN>y?xq$*AS(AIhf^5BveM%f= z2muAuGW+tUC8kE1S=8p3C;?8+NL+|3hOBc|l}3j+ms z44vy!!fmW0i=zv4L54EPc~tjLb#ry?Z0nE&JC*KHySP;7 nNprwF!^9`9tSZXSjMe7=3{){Bq6Hh#00000NkvXXu0mjf!OOSk diff --git a/platform/icons/src/_cvs/testInProgress5.png b/platform/icons/src/_cvs/testInProgress5.png deleted file mode 100644 index 5a5811ff77dd882145becf09cd93f5d95c3141c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 812 zcmV+{1JnG8P) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~w|v|H(Z0 ze=7NcF!_Qp`G`7NWn}%)wEo9M|GXssyfgWJD*wq_|I1we%}M{xQ~&><|No)-mq_}Y zQv04@|G_c;!ZiQJI{(H<`=Vz2r#}3uKK!tJ{IGrevQhlBX8g5k{JB~DyIlOdU;V$8 zsj`Bsw1WA1BzJ^%eTsMbjx+j@H~Nq`|F=Kk@H|F$3h z&TRkBWB<=>|Il>*(M^?|K*PV<*xtctpDh8|LLm#>T>_4Qv1a0MSWAK~xx5V_?7r7`X)%Gdn%I^fdXQ-#Z7@`7N$|5Q`1KIqEP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~^BW|Noi! zf-w1lG5Lr(`in67jWzm?Gy0G>`j9yKlRo;FNcx;o{mZHUyd?k0JpajC|I1we%}M{x zQ~%Cv|IcIp&u#zEbpO#z|ItnV)ldJ`Q2Bl;|LAi6>8k(ga{udf|LeN{?0Em}y#MXS z|L(*8^V$FO+4+Ae|Nox<|DXT=p#T4&Sz=%Ryfgp4JpaHf|H3r?#ybDTNL^l2Wn@%= zf@Oz}Z$*M^?|K*PV<*xtcto*fV{JB~DyIlOdU;V$8`FbS%(X{@@MgHHa z{_y7h@s9ttAOG~)|MlJf`j7wqm;bjS|Nol*|C|5+o&UHW|G6#yx+VX-BX!zTg8%>k zGjvi;QvfO}D^*ohR#sM5W@l$$VwM7$=1H5WMK`se#O%@hI( zsCh;N+IRM}n_1NOIw}DLR9tEsYzrN7{H;Q(lNEsiVu@vSMW*J_9jy}sQiOp5Jch2B z*)2BKZN1ZibU}tP$)zV`O`2k2GBwUe66{!Zt&HHf*qHd3N(~l>Q@Lb~yp4^^^`tpq ko?+q>S5_6}XU6Jt09&{*8Zhj?@c;k-07*qoM6N<$g3JTAEC2ui diff --git a/platform/icons/src/_cvs/testInProgress7.png b/platform/icons/src/_cvs/testInProgress7.png deleted file mode 100644 index 5b1835a5e1b8bb71fec8c8b5639cf5a1c96d3bd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 806 zcmV+>1KIqEP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~?l{|H(Z6 z|DO4RG5Lr(`in67jWzm?GyTh{`F<+@yfgWKD*wq_|IJDN=yCu5nfZb+|No%>|Dpf4 zBLBD_|G6#yx+VX+CI7r5T3=sUU}OKjJpaHf|G_c;!ZiQJI{(HesQU#jQX5X z`<`I?qGtT3KK!aa{IGoduzmcpQUBFy|JQ~8*lYjUT>sgQ|Jqys=yLz+a{udf|LeN{ z?0Em}y#MXS|MP_Z^V#~7KKhqP`j9vM(X{{0Q~%Cv|IcIp&~*RNO#jhM|J6_b)lmA7 zIRDy*|J_{w-(vsYWdGr8|KfT7MfB->U!g+5hy~|MlJf`j7wqm;U2-|Nol*|C|5+o&NCV|No!<@s9ttA6+zH^Z)<= zGjvi;QvfO}D^*ohR#sM5W@l$+`f#)_@W?VHwlm~Uj6L;-j;mJs2&qzh&e`0qyM1D6pfFH?$IzjE za$8kF$INMIx*$WDIRzSMT3{zLr6b%-LQ@Lb~${Zb&^rSgp ko?+q>S5_6}XU6Jt0OlAl!JWRuF8}}l07*qoM6N<$g0h3S;Q#;t diff --git a/platform/icons/src/_cvs/testInProgress8.png b/platform/icons/src/_cvs/testInProgress8.png deleted file mode 100644 index bfc1339045f9dfddf886543e587fc42ea7f0bce3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 806 zcmV+>1KIqEP) zUI3zB0HR<4reg!9V+5vT2B%^Gr(^@CWCW;V0H9s~pV6bp*qC3eS=&(TW(+k0#TB1oE#h@~|-Tu`ctpF!Q=s^SoB{q7n3{8~^BW{mZHO zf-w1lG5Lr(`in67jWz%Ong6^b|H(Z6$y@)+T>s5U|ISnY&TRR9D*ykU|No%>|Dpf8 zCI7r5U1Vtgyfgp4JpaHf|G_c;!ZiQJI{(Hsx<|KDW);En&$P5;$T`j9vO z=yLz*s{iV8|Lb-C>$?B!c>nFZ|Lw;A?!*7{g!z9e`j9yP|DXDkKKhqP`kYexo?!Zp zGyl(H|Icmz&~*RNO#k6*|KfT7U3| z{>MfB<9Gh>=Kk@H|MlJf`j7wqm;bgO|Nol*|C|5+o&UEY|F|Fjxh?;?CGcS{DF6Tf zGjvi;QvfO}D^*ohR#sM5W@l$V;%ggr%Qlz@#+@@1xJ@#hV|IEYjXnyL~1AGw?>$RI)%sB%n||$ zsMQo^Rdn}tnpvczTPpztRP0il$|6lFovQMZy%m81VxDmgQKsg_A?*`0eT9JnJcjo5 zy=^5K9sSd?bwP$Q$+;yJO`2k5HPt0e66{!ZEuS2hQfF7^1PvC5Q@Lb~>Wq!!^`tpq ko?+q>S5_6}XU6Jt00G)C$dud-ZvX%Q07*qoM6N<$f+do$PXGV_ diff --git a/platform/icons/src/_cvs/unknown.png b/platform/icons/src/_cvs/unknown.png deleted file mode 100644 index c3db35b2d4d51d1b8d1c656897553d004a481752..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 199 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv3GfMV)pt(#|NlRb#DkI-Kh_7T z=P3#D3ua)j@atN%YQv_jJJ0+MblL_Kck^^{4B?1Q7HDB&^J)8%w?N_WyI!74d}nr- zOK)h9xWjlyTA_y}lcTw@a2r$0!L6N)haTKuNHySE(7nNVNtrPN_MLZ diff --git a/platform/icons/src/_cvs/showAsTree.png b/platform/icons/src/actions/showAsTree.png similarity index 100% rename from platform/icons/src/_cvs/showAsTree.png rename to platform/icons/src/actions/showAsTree.png diff --git a/platform/platform-resources/platform-resources.iml b/platform/platform-resources/platform-resources.iml index b02a4aad9114..dcae9c1f00d4 100644 --- a/platform/platform-resources/platform-resources.iml +++ b/platform/platform-resources/platform-resources.iml @@ -8,6 +8,7 @@ + diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml index 91f17d8d3798..0070165c10b3 100644 --- a/platform/platform-resources/src/idea/VcsActions.xml +++ b/platform/platform-resources/src/idea/VcsActions.xml @@ -1,7 +1,7 @@ + icon="AllIcons.Actions.ShowAsTree"/> @@ -48,7 +48,7 @@ text = "VCS Operations Popup..." description="Context aware popup with list of commonly used VCS actions"/> - + diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index 9c33157063b8..b77a5823b58d 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -6,26 +6,6 @@ import javax.swing.*; public class AllIcons { - public static class _cvs { - public static final Icon CheckOut = IconLoader.getIcon("/_cvs/checkOut.png"); - public static final Icon Cvs = IconLoader.getIcon("/_cvs/cvs.png"); - public static final Icon HideMissing = IconLoader.getIcon("/_cvs/hideMissing.png"); - public static final Icon HideUnknown = IconLoader.getIcon("/_cvs/hideUnknown.png"); - public static final Icon HideUptodate = IconLoader.getIcon("/_cvs/hideUptodate.png"); - public static final Icon Missing = IconLoader.getIcon("/_cvs/missing.png"); - public static final Icon ShowAsTree = IconLoader.getIcon("/_cvs/showAsTree.png"); - public static final Icon TestInProgress1 = IconLoader.getIcon("/_cvs/testInProgress1.png"); - public static final Icon TestInProgress2 = IconLoader.getIcon("/_cvs/testInProgress2.png"); - public static final Icon TestInProgress3 = IconLoader.getIcon("/_cvs/testInProgress3.png"); - public static final Icon TestInProgress4 = IconLoader.getIcon("/_cvs/testInProgress4.png"); - public static final Icon TestInProgress5 = IconLoader.getIcon("/_cvs/testInProgress5.png"); - public static final Icon TestInProgress6 = IconLoader.getIcon("/_cvs/testInProgress6.png"); - public static final Icon TestInProgress7 = IconLoader.getIcon("/_cvs/testInProgress7.png"); - public static final Icon TestInProgress8 = IconLoader.getIcon("/_cvs/testInProgress8.png"); - public static final Icon Unknown = IconLoader.getIcon("/_cvs/unknown.png"); - - } - public static class Actions { public static final Icon AddFacesSupport = IconLoader.getIcon("/actions/addFacesSupport.png"); public static final Icon Annotate = IconLoader.getIcon("/actions/annotate.png"); @@ -155,6 +135,7 @@ public class AllIcons { public static final Icon Search = IconLoader.getIcon("/actions/search.png"); public static final Icon Selectall = IconLoader.getIcon("/actions/selectall.png"); public static final Icon Share = IconLoader.getIcon("/actions/share.png"); + public static final Icon ShowAsTree = IconLoader.getIcon("/actions/showAsTree.png"); public static final Icon ShowChangesOnly = IconLoader.getIcon("/actions/showChangesOnly.png"); public static final Icon ShowHiddens = IconLoader.getIcon("/actions/showHiddens.png"); public static final Icon ShowImportStatements = IconLoader.getIcon("/actions/showImportStatements.png"); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/CvsTabbedWindow.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/CvsTabbedWindow.java index 7eb880e46b1f..e5760a40ea9b 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/CvsTabbedWindow.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/ui/CvsTabbedWindow.java @@ -108,7 +108,7 @@ public class CvsTabbedWindow { ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); ToolWindow toolWindow = toolWindowManager.registerToolWindow(ToolWindowId.CVS, myContentManager.getComponent(), ToolWindowAnchor.BOTTOM); - toolWindow.setIcon(AllIcons._cvs.Cvs); + toolWindow.setIcon(AllIcons.Actions.Cvs); toolWindow.installWatcher(myContentManager); } From 9a6609fa5b71b81378c1630b27d9b25047dfe77d Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 31 May 2012 22:05:53 +0400 Subject: [PATCH 050/239] gimme some speedsearching! --- .../com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java index 77b81e18bd09..49df3c099ec7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/FileHistoryPanelImpl.java @@ -398,6 +398,7 @@ public class FileHistoryPanelImpl extends PanelWithActionsAndCloseButton { storageKey, myVcs.getProject()); myDualView.switchToTheFlatMode(); } + new TableSpeedSearch(myDualView.getFlatView()).setComparator(new SpeedSearchComparator(false)); final TableLinkMouseListener listener = new TableLinkMouseListener(); listener.install(myDualView.getFlatView()); listener.install(myDualView.getTreeView()); From 96b3e6c75d9c1d39281d25b1113230e43cbda38d Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 19:38:42 +0200 Subject: [PATCH 051/239] IDEA-22219 Spring Webflow: When editing spring webflow xml, the cursor jumps all over the place --- .../template/macro/BaseCompleteMacro.java | 67 ++++++++----------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/BaseCompleteMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/BaseCompleteMacro.java index 19c21c2fa03e..953e0cc76859 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/BaseCompleteMacro.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/BaseCompleteMacro.java @@ -29,7 +29,6 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilBase; import org.jetbrains.annotations.NonNls; @@ -72,50 +71,37 @@ public abstract class BaseCompleteMacro extends Macro { final Editor editor = context.getEditor(); final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project); - new WriteCommandAction.Simple(project, psiFile) { - public void run() { - PsiDocumentManager.getInstance(project).commitAllDocuments(); - } - }.execute(); - - if (ApplicationManager.getApplication().isUnitTestMode()) { - getCompletionHandler().invoke(project, editor, psiFile); - return; - } - - ApplicationManager.getApplication().invokeLater(new Runnable() { + Runnable runnable = new Runnable() { + @Override public void run() { - if (project.isDisposed()) return; + if (project.isDisposed() || editor.isDisposed() || psiFile == null || !psiFile.isValid()) return; - CommandProcessor.getInstance().executeCommand( - project, new Runnable() { - public void run() { - if (!ApplicationManager.getApplication().isUnitTestMode()) { - getCompletionHandler().invoke(project, editor, psiFile); - } + CommandProcessor.getInstance().executeCommand(project, new Runnable() { + public void run() { + getCompletionHandler().invoke(project, editor, psiFile); + Lookup lookup = LookupManager.getInstance(project).getActiveLookup(); - final LookupManager lookupManager = LookupManager.getInstance(project); - Lookup lookup = lookupManager.getActiveLookup(); - - if (lookup != null) { - lookup.addLookupListener(new MyLookupListener(context)); - } - else { - TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); - if (templateState != null) { - TextRange range = templateState.getCurrentVariableRange(); - if (range != null && range.getLength() > 0/* && TemplateEditorUtil.getOffset(editor) == range.getEndOffset()*/) { - templateState.nextTab(); - } + if (lookup != null) { + lookup.addLookupListener(new MyLookupListener(context)); + } + else { + TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + if (templateState != null) { + TextRange range = templateState.getCurrentVariableRange(); + if (range != null && range.getLength() > 0/* && TemplateEditorUtil.getOffset(editor) == range.getEndOffset()*/) { + templateState.nextTab(); } } } - }, - "", - null - ); + } + }, "", null); } - }); + }; + if (ApplicationManager.getApplication().isUnitTestMode()) { + runnable.run(); + } else { + ApplicationManager.getApplication().invokeLater(runnable); + } } private static class MyLookupListener extends LookupAdapter { @@ -129,6 +115,11 @@ public abstract class BaseCompleteMacro extends Macro { LookupElement item = event.getItem(); if (item == null) return; + char c = event.getCompletionChar(); + if (c != Lookup.REPLACE_SELECT_CHAR && c != Lookup.NORMAL_SELECT_CHAR && c != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) { + return; + } + for(TemplateCompletionProcessor processor: Extensions.getExtensions(TemplateCompletionProcessor.EP_NAME)) { if (!processor.nextTabOnItemSelected(myContext, item)) { return; From bb675ab516c19176c1140a009feb02efe66146a3 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 31 May 2012 20:00:03 +0200 Subject: [PATCH 052/239] make lookup list size not divisible by lookup item height to make more obvious that it's scrollable --- .../com/intellij/codeInsight/lookup/impl/LookupImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 2494d208a23a..f86768899ceb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -1359,8 +1359,11 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable int scrollBarWidth = myScrollPane.getPreferredSize().width - myScrollPane.getViewport().getPreferredSize().width; int listWidth = Math.min(scrollBarWidth + maxCellWidth, UISettings.getInstance().MAX_LOOKUP_WIDTH2); int adWidth = myAdComponent.getAdComponent().getPreferredSize().width; - return new Dimension(Math.max(listWidth, adWidth), - Math.min(mainPanel.getPreferredSize().height, myMaximumHeight)); + int panelHeight = mainPanel.getPreferredSize().height; + if (myList.getModel().getSize() > myList.getVisibleRowCount() && myList.getVisibleRowCount() > 5) { + panelHeight -= myList.getFixedCellHeight() / 2; + } + return new Dimension(Math.max(listWidth, adWidth), Math.min(panelHeight, myMaximumHeight)); } @Override From 815d34448ecedf1a3c02a93f871b1e9b88e5ec18 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 1 Jun 2012 01:47:07 +0400 Subject: [PATCH 053/239] - when resizing the file, unmap only last page, all others can be used - force affect only dirty bytebuffers --- .../intellij/util/io/ByteBufferWrapper.java | 9 + .../intellij/util/io/DirectBufferWrapper.java | 2 +- .../intellij/util/io/MappedBufferWrapper.java | 10 +- .../intellij/util/io/PagedFileStorage.java | 441 +++++++++--------- 4 files changed, 240 insertions(+), 222 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java index bbfe788f0955..c6527821fd3e 100644 --- a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java @@ -27,6 +27,7 @@ public abstract class ByteBufferWrapper { protected final File myFile; protected final long myPosition; protected final long myLength; + protected volatile boolean myDirty; protected ByteBufferWrapper(final File file, final long offset, final long length) { myFile = file; @@ -37,6 +38,14 @@ public abstract class ByteBufferWrapper { @Nullable public abstract ByteBuffer getCachedBuffer(); + public final void markDirty() { + if (!myDirty) myDirty = true; + } + + public final boolean isDirty() { + return myDirty; + } + public abstract ByteBuffer getBuffer() throws IOException; public abstract void unmap(); diff --git a/platform/util/src/com/intellij/util/io/DirectBufferWrapper.java b/platform/util/src/com/intellij/util/io/DirectBufferWrapper.java index f944cbe335b4..00049a0619fa 100644 --- a/platform/util/src/com/intellij/util/io/DirectBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/DirectBufferWrapper.java @@ -48,7 +48,7 @@ public abstract class DirectBufferWrapper extends ByteBufferWrapper { @Override public void unmap() { - flush(); + if (isDirty()) flush(); myBuffer = null; } } diff --git a/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java b/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java index d2a5455ec1cf..0f86ffa4d433 100644 --- a/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/MappedBufferWrapper.java @@ -48,7 +48,7 @@ public abstract class MappedBufferWrapper extends ByteBufferWrapper { long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0; MappedByteBuffer buffer = myBuffer; myBuffer = null; - if (!clean(buffer)) { + if (!clean(buffer, isDirty())) { LOG.error("Unmapping failed for: " + myFile); } @@ -74,10 +74,10 @@ public abstract class MappedBufferWrapper extends ByteBufferWrapper { return buffer; } - private static boolean clean(final MappedByteBuffer buffer) { + private static boolean clean(final MappedByteBuffer buffer, boolean dirty) { if (buffer == null) return true; - if (!tryForce(buffer)) { + if (dirty && !tryForce(buffer)) { return false; } @@ -117,8 +117,8 @@ public abstract class MappedBufferWrapper extends ByteBufferWrapper { @Override public void flush() { final MappedByteBuffer buffer = myBuffer; - if (buffer != null) { - tryForce(buffer); + if (buffer != null && isDirty()) { + if(tryForce(buffer)) myDirty = false; } } } diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index 88c13ce23b9e..ba943184c4a2 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -83,211 +83,17 @@ public class PagedFileStorage implements Forceable { private static final int MAX_LIVE_STORAGES_COUNT = 0xFFFF; public void lock() { - myStorageLockContext.myReentrantLock.lock(); + myStorageLockContext.myLock.lock(); } public void unlock() { - myStorageLockContext.myReentrantLock.unlock(); + myStorageLockContext.myLock.unlock(); } public StorageLockContext getStorageLockContext() { return myStorageLockContext; } - public static class StorageLock { - private static final int FILE_INDEX_MASK = 0xFFFF0000; - private static final int FILE_INDEX_SHIFT = 16; - private final boolean checkThreadAccess; - public final StorageLockContext myDefaultStorageLockContext; - - public StorageLock() { - this(true); - } - - public StorageLock(boolean checkThreadAccess) { - this.checkThreadAccess = checkThreadAccess; - myDefaultStorageLockContext = new StorageLockContext(this); - } - - public void lock() { - myDefaultStorageLockContext.myReentrantLock.lock(); - } - - public void unlock() { - myDefaultStorageLockContext.myReentrantLock.unlock(); - } - - private final BuffersCache myBuffersCache = new BuffersCache(); - private final ConcurrentHashMap myIndex2Storage = new ConcurrentHashMap(); - - private int registerPagedFileStorage(PagedFileStorage storage) { - int registered = myIndex2Storage.size(); - assert registered <= MAX_LIVE_STORAGES_COUNT; - int value = registered << FILE_INDEX_SHIFT; - while(myIndex2Storage.putIfAbsent(value, storage) != null) { - ++registered; - assert registered <= MAX_LIVE_STORAGES_COUNT; - value = registered << FILE_INDEX_SHIFT; - } - return value; - } - - private PagedFileStorage getRegisteredPagedFileStorageByIndex(int index) { - return myIndex2Storage.get(index); - } - - private class BuffersCache { - private int changeCount; - private final LinkedHashMap myMap; - private long mySizeLimit; - private long mySize; - - private BuffersCache() { - mySizeLimit = UPPER_LIMIT; - myMap = new LinkedHashMap(10) { - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return mySize > mySizeLimit; - } - - @Nullable - @Override - public ByteBufferWrapper remove(Object key) { - // this method can be called after removeEldestEntry - ByteBufferWrapper wrapper = super.remove(key); - if (wrapper != null) { - mySize -= wrapper.myLength; - wrapper.dispose(); - } - return wrapper; - } - }; - } - - private ByteBufferWrapper get(Integer key) { - ByteBufferWrapper wrapper = myMap.get(key); - if (wrapper != null) { - return wrapper; - } - - long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0; - wrapper = createValue(key); - mySize += wrapper.myLength; - - if (IOStatistics.DEBUG) { - long finished = System.currentTimeMillis(); - if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) { - IOStatistics.dump( - "Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started)); - } - } - myMap.put(key, wrapper); - - ensureSize(mySizeLimit); - return wrapper; - } - - private void ensureSize(long sizeLimit) { - while (mySize > sizeLimit) { - // we still have to drop something - myMap.doRemoveEldestEntry(); - } - } - - @NotNull - private ByteBufferWrapper createValue(Integer key) { - final int storageIndex = key & FILE_INDEX_MASK; - PagedFileStorage owner = getRegisteredPagedFileStorageByIndex(storageIndex); - assert owner != null: "No storage for index " + storageIndex; - checkThreadAccess(owner.myStorageLockContext); - int off = (key & MAX_PAGES_COUNT) * owner.myPageSize; - if (off > owner.length()) { - throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length()); - } - ++changeCount; - ByteBufferWrapper wrapper = ByteBufferWrapper.readWrite(owner.myFile, off, Math.min((int)(owner.length() - off), owner.myPageSize)); - IOException oome = null; - while (true) { - try { - // ensure it's allocated - wrapper.getBuffer(); - if (oome != null) { - LOG.info("Successfully recovered OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " + - "new size limit: " + mySizeLimit / MB + "MB " + - "trying to allocate " + wrapper.myLength + " block"); - } - return wrapper; - } - catch (IOException e) { - if (e.getCause() instanceof OutOfMemoryError) { - oome = e; - if (mySizeLimit > LOWER_LIMIT) { - mySizeLimit -= owner.myPageSize; - } - long newSize = mySize - owner.myPageSize; - if (newSize >= 0) { - ensureSize(newSize); - continue; // next try - } - else { - throw new MappingFailedException( - "Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " + - "new size limit: " + mySizeLimit / MB + "MB " + - "trying to allocate " + wrapper.myLength + " block", e); - } - } - throw new MappingFailedException("Cannot map buffer", e); - } - } - } - - private void checkThreadAccess(StorageLockContext storageLockContext) { - if (checkThreadAccess && !storageLockContext.myReentrantLock.isHeldByCurrentThread()) { - throw new IllegalStateException("Must hold StorageLock lock to access PagedFileStorage"); - } - } - - private @Nullable Map getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) { - checkThreadAccess(storageLockContext); - Map mineBuffers = null; - for (Map.Entry entry : myMap.entrySet()) { - if ((entry.getKey() & FILE_INDEX_MASK) == index) { - if (mineBuffers == null) { - mineBuffers = new TreeMap(new Comparator() { - @Override - public int compare(Integer o1, Integer o2) { - return o1 - o2; - } - }); - } - mineBuffers.put(entry.getKey(), entry.getValue()); - } - } - return mineBuffers; - } - - private void unmapBuffersForOwner(int index, StorageLockContext storageLockContext) { - final Map buffers = getBuffersOrderedForOwner(index, storageLockContext); - - if (buffers != null) { - for (Integer key : buffers.keySet()) { - myMap.remove(key); - } - } - } - - private void flushBuffersForOwner(int index, StorageLockContext storageLockContext) { - Map buffers = getBuffersOrderedForOwner(index, storageLockContext); - - if (buffers != null) { - for(ByteBufferWrapper buffer:buffers.values()) { - buffer.flush(); - } - } - } - } - } - private final byte[] myTypedIOBuffer; private boolean isDirty = false; private final File myFile; @@ -305,7 +111,7 @@ public class PagedFileStorage implements Forceable { myStorageLockContext = storageLockContext; myPageSize = Math.max(pageSize > 0 ? pageSize : BUFFER_SIZE, Page.PAGE_SIZE); myValuesAreBufferAligned = valuesAreBufferAligned; - myStorageIndex = storageLockContext.myLock.registerPagedFileStorage(this); + myStorageIndex = storageLockContext.myStorageLock.registerPagedFileStorage(this); myTypedIOBuffer = valuesAreBufferAligned ? null:new byte[8]; } public PagedFileStorage(File file, StorageLock lock) throws IOException { @@ -332,7 +138,7 @@ public class PagedFileStorage implements Forceable { if (myValuesAreBufferAligned) { int page = addr / myPageSize; int page_offset = addr % myPageSize; - return getBuffer(page).getInt(page_offset); + return getBuffer(page, false).getInt(page_offset); } else { get(addr, myTypedIOBuffer, 0, 4); return Bits.getInt(myTypedIOBuffer, 0); @@ -363,7 +169,7 @@ public class PagedFileStorage implements Forceable { if (myValuesAreBufferAligned) { int page = addr / myPageSize; int page_offset = addr % myPageSize; - return getBuffer(page).getShort(page_offset); + return getBuffer(page, false).getShort(page_offset); } else { get(addr, myTypedIOBuffer, 0, 2); return Bits.getShort(myTypedIOBuffer, 0); @@ -395,7 +201,7 @@ public class PagedFileStorage implements Forceable { if (myValuesAreBufferAligned) { int page = addr / myPageSize; int page_offset = addr % myPageSize; - return getBuffer(page).getLong(page_offset); + return getBuffer(page, false).getLong(page_offset); } else { get(addr, myTypedIOBuffer, 0, 8); return Bits.getLong(myTypedIOBuffer, 0); @@ -406,7 +212,7 @@ public class PagedFileStorage implements Forceable { int page = index / myPageSize; int offset = index % myPageSize; - return getBuffer(page).get(offset); + return getBuffer(page, false).get(offset); } public void put(int index, byte value) { @@ -427,7 +233,7 @@ public class PagedFileStorage implements Forceable { int page_offset = i % myPageSize; int page_len = Math.min(l, myPageSize - page_offset); - final ByteBuffer buffer = getBuffer(page); + final ByteBuffer buffer = getBuffer(page, false); try { buffer.position(page_offset); } @@ -478,13 +284,13 @@ public class PagedFileStorage implements Forceable { } finally { unmapAll(); - myStorageLockContext.myLock.myIndex2Storage.remove(myStorageIndex); + myStorageLockContext.myStorageLock.myIndex2Storage.remove(myStorageIndex); myStorageIndex = -1; } } private void unmapAll() { - myStorageLockContext.myLock.myBuffersCache.unmapBuffersForOwner(myStorageIndex, myStorageLockContext); + myStorageLockContext.myStorageLock.unmapBuffersForOwner(myStorageIndex, myStorageLockContext); myLastPage = UNKNOWN_PAGE; myLastPage2 = UNKNOWN_PAGE; @@ -497,7 +303,8 @@ public class PagedFileStorage implements Forceable { if (oldSize == newSize) return; final long started = IOStatistics.DEBUG ? System.currentTimeMillis():0; - unmapAll(); + myStorageLockContext.myStorageLock.invalidateBuffer((int)(myStorageIndex | (mySize / myPageSize))); + //unmapAll(); final long unmapAllFinished = IOStatistics.DEBUG ? System.currentTimeMillis():0; resizeFile(newSize); @@ -539,7 +346,6 @@ public class PagedFileStorage implements Forceable { } } - public final long length() { if (mySize == -1) { mySize = myFile.length(); @@ -548,23 +354,34 @@ public class PagedFileStorage implements Forceable { } private ByteBuffer getBuffer(int page) { + return getBuffer(page, true); + } + + private ByteBuffer getBuffer(int page, boolean modify) { if (myLastPage == page) { ByteBuffer buf = myLastBuffer.getCachedBuffer(); - if (buf != null && myLastChangeCount == myStorageLockContext.myLock.myBuffersCache.changeCount) return buf; + if (buf != null && myLastChangeCount == myStorageLockContext.myStorageLock.myMappingChangeCount) { + if (modify) myLastBuffer.markDirty(); + return buf; + } } if (myLastPage2 == page) { ByteBuffer buf = myLastBuffer2.getCachedBuffer(); - if (buf != null && myLastChangeCount2 == myStorageLockContext.myLock.myBuffersCache.changeCount) return buf; + if (buf != null && myLastChangeCount2 == myStorageLockContext.myStorageLock.myMappingChangeCount) { + if (modify) myLastBuffer2.markDirty(); + return buf; + } } try { assert page <= MAX_PAGES_COUNT; if (myStorageIndex == -1) { - myStorageIndex = myStorageLockContext.myLock.registerPagedFileStorage(this); + myStorageIndex = myStorageLockContext.myStorageLock.registerPagedFileStorage(this); } - ByteBufferWrapper byteBufferWrapper = myStorageLockContext.myLock.myBuffersCache.get(myStorageIndex | page); + ByteBufferWrapper byteBufferWrapper = myStorageLockContext.myStorageLock.get(myStorageIndex | page); + if (modify) byteBufferWrapper.markDirty(); ByteBuffer buf = byteBufferWrapper.getBuffer(); if (myLastPage != page) { @@ -577,7 +394,7 @@ public class PagedFileStorage implements Forceable { myLastBuffer = byteBufferWrapper; } - myLastChangeCount = myStorageLockContext.myLock.myBuffersCache.changeCount; + myLastChangeCount = myStorageLockContext.myStorageLock.myMappingChangeCount; return buf; } @@ -588,7 +405,7 @@ public class PagedFileStorage implements Forceable { public void force() { long started = IOStatistics.DEBUG ? System.currentTimeMillis():0; - myStorageLockContext.myLock.myBuffersCache.flushBuffersForOwner(myStorageIndex, myStorageLockContext); + myStorageLockContext.myStorageLock.flushBuffersForOwner(myStorageIndex, myStorageLockContext); isDirty = false; if (IOStatistics.DEBUG) { @@ -603,13 +420,205 @@ public class PagedFileStorage implements Forceable { return isDirty; } + public static class StorageLock { + private static final int FILE_INDEX_MASK = 0xFFFF0000; + private static final int FILE_INDEX_SHIFT = 16; + private final boolean checkThreadAccess; + public final StorageLockContext myDefaultStorageLockContext; + + private int myMappingChangeCount; + private final LinkedHashMap myMap; + private long mySizeLimit; + private long mySize; + private final ConcurrentHashMap myIndex2Storage = new ConcurrentHashMap(); + + public StorageLock() { + this(true); + } + + public StorageLock(boolean checkThreadAccess) { + this.checkThreadAccess = checkThreadAccess; + myDefaultStorageLockContext = new StorageLockContext(this); + + mySizeLimit = UPPER_LIMIT; + myMap = new LinkedHashMap(10) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return mySize > mySizeLimit; + } + + @Nullable + @Override + public ByteBufferWrapper remove(Object key) { + // this method can be called after removeEldestEntry + ByteBufferWrapper wrapper = super.remove(key); + if (wrapper != null) { + mySize -= wrapper.myLength; + wrapper.dispose(); + } + return wrapper; + } + }; + } + + public void lock() { + myDefaultStorageLockContext.myLock.lock(); + } + + public void unlock() { + myDefaultStorageLockContext.myLock.unlock(); + } + + private int registerPagedFileStorage(PagedFileStorage storage) { + int registered = myIndex2Storage.size(); + assert registered <= MAX_LIVE_STORAGES_COUNT; + int value = registered << FILE_INDEX_SHIFT; + while(myIndex2Storage.putIfAbsent(value, storage) != null) { + ++registered; + assert registered <= MAX_LIVE_STORAGES_COUNT; + value = registered << FILE_INDEX_SHIFT; + } + return value; + } + + private PagedFileStorage getRegisteredPagedFileStorageByIndex(int index) { + return myIndex2Storage.get(index); + } + + private ByteBufferWrapper get(Integer key) { + ByteBufferWrapper wrapper = myMap.get(key); + if (wrapper != null) { + return wrapper; + } + + long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0; + wrapper = createValue(key); + mySize += wrapper.myLength; + + if (IOStatistics.DEBUG) { + long finished = System.currentTimeMillis(); + if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) { + IOStatistics.dump( + "Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started)); + } + } + myMap.put(key, wrapper); + + ensureSize(mySizeLimit); + return wrapper; + } + + private void ensureSize(long sizeLimit) { + while (mySize > sizeLimit) { + // we still have to drop something + myMap.doRemoveEldestEntry(); + } + } + + @NotNull + private ByteBufferWrapper createValue(Integer key) { + final int storageIndex = key & FILE_INDEX_MASK; + PagedFileStorage owner = getRegisteredPagedFileStorageByIndex(storageIndex); + assert owner != null: "No storage for index " + storageIndex; + checkThreadAccess(owner.myStorageLockContext); + int off = (key & MAX_PAGES_COUNT) * owner.myPageSize; + if (off > owner.length()) { + throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length()); + } + ++myMappingChangeCount; + ByteBufferWrapper wrapper = ByteBufferWrapper.readWrite(owner.myFile, off, Math.min((int)(owner.length() - off), owner.myPageSize)); + IOException oome = null; + while (true) { + try { + // ensure it's allocated + wrapper.getBuffer(); + if (oome != null) { + LOG.info("Successfully recovered OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " + + "new size limit: " + mySizeLimit / MB + "MB " + + "trying to allocate " + wrapper.myLength + " block"); + } + return wrapper; + } + catch (IOException e) { + if (e.getCause() instanceof OutOfMemoryError) { + oome = e; + if (mySizeLimit > LOWER_LIMIT) { + mySizeLimit -= owner.myPageSize; + } + long newSize = mySize - owner.myPageSize; + if (newSize >= 0) { + ensureSize(newSize); + continue; // next try + } + else { + throw new MappingFailedException( + "Cannot recover from OOME in memory mapping: -Xmx=" + Runtime.getRuntime().maxMemory() / MB + "MB " + + "new size limit: " + mySizeLimit / MB + "MB " + + "trying to allocate " + wrapper.myLength + " block", e); + } + } + throw new MappingFailedException("Cannot map buffer", e); + } + } + } + + private void checkThreadAccess(StorageLockContext storageLockContext) { + if (checkThreadAccess && !storageLockContext.myLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Must hold StorageLock lock to access PagedFileStorage"); + } + } + + private @Nullable Map getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) { + checkThreadAccess(storageLockContext); + Map mineBuffers = null; + for (Map.Entry entry : myMap.entrySet()) { + if ((entry.getKey() & FILE_INDEX_MASK) == index) { + if (mineBuffers == null) { + mineBuffers = new TreeMap(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o1 - o2; + } + }); + } + mineBuffers.put(entry.getKey(), entry.getValue()); + } + } + return mineBuffers; + } + + private void unmapBuffersForOwner(int index, StorageLockContext storageLockContext) { + final Map buffers = getBuffersOrderedForOwner(index, storageLockContext); + + if (buffers != null) { + for (Integer key : buffers.keySet()) { + myMap.remove(key); + } + } + } + + private void flushBuffersForOwner(int index, StorageLockContext storageLockContext) { + Map buffers = getBuffersOrderedForOwner(index, storageLockContext); + + if (buffers != null) { + for(ByteBufferWrapper buffer:buffers.values()) { + buffer.flush(); + } + } + } + + public void invalidateBuffer(int page) { + myMap.remove(page); + } + } + public static class StorageLockContext { - private final SequenceLock myReentrantLock; - private final StorageLock myLock; + private final SequenceLock myLock; + private final StorageLock myStorageLock; public StorageLockContext(StorageLock lock) { - myReentrantLock = new SequenceLock(); - myLock = lock; + myLock = new SequenceLock(); + myStorageLock = lock; } } } From e6aaec790218ee73d12dfca0d6e3ad8b10a0b4d9 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 10:27:19 +0400 Subject: [PATCH 054/239] correct introduce parameter for incorrect calls --- .../GroovyIntroduceParameterMethodUsagesProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 1493d3f73d0d..27718ffc13b8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -103,7 +103,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP final GrClosureSignatureUtil.ArgInfo[] actualArgs = GrClosureSignatureUtil .mapParametersToArguments(signature, callExpression.getNamedArguments(), callExpression.getExpressionArguments(), - callExpression.getClosureArguments(), callExpression, true, true); + callExpression.getClosureArguments(), callExpression, false, true); final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(data.getProject()); From da7fd75bf05b7bc298aabd4f983d5da07471cdf5 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 1 Jun 2012 11:20:43 +0400 Subject: [PATCH 055/239] allocate last non aligned buffer as direct bytebuffer, it is cheaper to close/flush it during resize --- .../util/src/com/intellij/util/io/ByteBufferWrapper.java | 4 ++++ .../util/src/com/intellij/util/io/PagedFileStorage.java | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java index c6527821fd3e..60efdd155c06 100644 --- a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java +++ b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java @@ -61,6 +61,10 @@ public abstract class ByteBufferWrapper { : new ReadWriteMappedBufferWrapper(file, offset, length); } + public static ByteBufferWrapper readWriteDirect(final File file, final int offset, final int length) { + return new ReadWriteDirectBufferWrapper(file, offset, length); + } + public static ByteBufferWrapper readOnly(final File file, final int offset) { return new ReadOnlyMappedBufferWrapper(file, offset); } diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java index ba943184c4a2..8cd61fa5aac1 100644 --- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java +++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java @@ -304,7 +304,7 @@ public class PagedFileStorage implements Forceable { final long started = IOStatistics.DEBUG ? System.currentTimeMillis():0; myStorageLockContext.myStorageLock.invalidateBuffer((int)(myStorageIndex | (mySize / myPageSize))); - //unmapAll(); + //unmapAll(); // we do not need it since all page alighned buffers can be reused final long unmapAllFinished = IOStatistics.DEBUG ? System.currentTimeMillis():0; resizeFile(newSize); @@ -526,7 +526,10 @@ public class PagedFileStorage implements Forceable { throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length()); } ++myMappingChangeCount; - ByteBufferWrapper wrapper = ByteBufferWrapper.readWrite(owner.myFile, off, Math.min((int)(owner.length() - off), owner.myPageSize)); + int min = Math.min((int)(owner.length() - off), owner.myPageSize); + ByteBufferWrapper wrapper = min != owner.myPageSize ? // last, non aligned buffer allocate directly, it is much faster to unmap it during resize + ByteBufferWrapper.readWriteDirect(owner.myFile, off, min): + ByteBufferWrapper.readWrite(owner.myFile, off, min); IOException oome = null; while (true) { try { From 2a73182e7c7625e8f1b193c024771daffae2cd06 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 1 Jun 2012 10:04:12 +0200 Subject: [PATCH 056/239] make change method signature works everywhere (UML, Project view, etc) --- .../actions/ChangeSignatureAction.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java index 1a845cf7c1c3..0d049d9a0c6f 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/actions/ChangeSignatureAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -23,10 +23,7 @@ import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiReference; +import com.intellij.psi.*; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.changeSignature.ChangeSignatureHandler; import org.jetbrains.annotations.NotNull; @@ -73,9 +70,14 @@ public class ChangeSignatureAction extends BaseRefactoringAction { final PsiElement targetMember = fileHandler.findTargetMember(element); if (targetMember != null) return targetMember; } - final PsiReference reference = element.getReference(); - if (reference == null) return null; - return reference.resolve(); + PsiReference reference = element.getReference(); + if (reference == null && element instanceof PsiNameIdentifierOwner) { + return element; + } + if (reference != null) { + return reference.resolve(); + } + return null; } @Override From e3928791c1493463ccd993aff59656677a1a80dd Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 30 May 2012 13:43:42 +0400 Subject: [PATCH 057/239] can have multiple test projects open --- .../daemon/quickFix/OrderEntryTest.java | 2 +- .../navigation/GotoImplementationTest.java | 2 +- .../intellij/psi/search/UpdateCacheTest.java | 4 +- .../openapi/project/ex/ProjectManagerEx.java | 6 +-- .../project/impl/ProjectManagerImpl.java | 38 +++++++++++-------- .../testFramework/LightPlatformTestCase.java | 16 ++++---- .../testFramework/PlatformTestCase.java | 10 +++-- .../impl/HeavyIdeaTestFixtureImpl.java | 2 +- 8 files changed, 43 insertions(+), 37 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java index d77be017306f..3a6ca8cc358a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java @@ -37,7 +37,7 @@ public class OrderEntryTest extends DaemonAnalyzerTestCase { VirtualFile projectFile = tempProjectRootDir.findChild("orderEntry.ipr"); myProject = ProjectManagerEx.getInstanceEx().loadProject(projectFile.getPath()); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); + ProjectManagerEx.getInstanceEx().openTestProject(myProject); ModuleManagerImpl mm = (ModuleManagerImpl)ModuleManager.getInstance(myProject); mm.projectOpened(); setUpJdk(); diff --git a/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationTest.java b/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationTest.java index b63f3672a9aa..d36f9ead9e07 100644 --- a/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationTest.java +++ b/java/java-tests/testSrc/com/intellij/navigation/GotoImplementationTest.java @@ -42,7 +42,7 @@ public class GotoImplementationTest extends CodeInsightTestCase { myProject = ProjectManagerEx.getInstanceEx().loadProject(projectFile.getPath()); simulateProjectOpen(); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); + ProjectManagerEx.getInstanceEx().openTestProject(myProject); } @Override diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java index 0b9b648d8507..e39f43603064 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -80,7 +80,7 @@ public class UpdateCacheTest extends PsiTestCase{ setUpJdk(); - myProjectManager.setCurrentTestProject(myProject); + myProjectManager.openTestProject(myProject); runStartupActivities(); } @@ -175,7 +175,7 @@ public class UpdateCacheTest extends PsiTestCase{ ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(getProject())).pushInjectors(); setUpModule(); setUpJdk(); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); + ProjectManagerEx.getInstanceEx().openTestProject(myProject); runStartupActivities(); PsiTestUtil.addSourceContentToRoots(getModule(), content); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java index d971eb44a2f7..ed2959ea53a1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.java @@ -51,12 +51,10 @@ public abstract class ProjectManagerEx extends ProjectManager { public abstract void blockReloadingProjectOnExternalChanges(); public abstract void unblockReloadingProjectOnExternalChanges(); - @Nullable @TestOnly - public abstract Project getCurrentTestProject(); - + public abstract void openTestProject(@NotNull Project project); @TestOnly - public abstract void setCurrentTestProject(@Nullable Project project); + public abstract void closeTestProject(@NotNull Project project); // returns true on success public abstract boolean closeAndDispose(@NotNull Project project); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 32886b248d1f..9bbb47458da0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -64,6 +64,7 @@ import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; +import gnu.trove.THashSet; import gnu.trove.TObjectLongHashMap; import org.jdom.Element; import org.jdom.JDOMException; @@ -95,7 +96,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt private Project[] myOpenProjectsArrayCache = {}; private final List myListeners = ContainerUtil.createEmptyCOWList(); - private Project myCurrentTestProject = null; + private final Set myTestProjects = new THashSet(); private final Map mySavedCopies = new HashMap(); private final TObjectLongHashMap mySavedTimestamps = new TObjectLongHashMap(); @@ -382,10 +383,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt LOG.error("Open projects cache corrupted. Open projects: "+myOpenProjects+"; cache: "+Arrays.asList(myOpenProjectsArrayCache)); } if (ApplicationManager.getApplication().isUnitTestMode()) { - Project currentTestProject = myCurrentTestProject; - if (currentTestProject != null && !currentTestProject.isDisposed()) { - return ArrayUtil.append(myOpenProjectsArrayCache, currentTestProject); - } + return ArrayUtil.mergeArrays(myOpenProjectsArrayCache, myTestProjects.toArray(new Project[myTestProjects.size()])); } return myOpenProjectsArrayCache; } @@ -393,10 +391,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt @Override public boolean isProjectOpened(Project project) { - if (ApplicationManager.getApplication().isUnitTestMode() && myCurrentTestProject != null) { - return project == myCurrentTestProject || myOpenProjects.contains(project); - } - return myOpenProjects.contains(project); + return ApplicationManager.getApplication().isUnitTestMode() && myTestProjects.contains(project) || myOpenProjects.contains(project); } @Override @@ -799,16 +794,29 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt } @Override - public void setCurrentTestProject(@Nullable final Project project) { + public void openTestProject(@NotNull final Project project) { assert ApplicationManager.getApplication().isUnitTestMode(); - myCurrentTestProject = project; + myTestProjects.add(project); } @Override - @Nullable - public Project getCurrentTestProject() { + public void closeTestProject(@NotNull Project project) { assert ApplicationManager.getApplication().isUnitTestMode(); - return myCurrentTestProject; + myTestProjects.remove(project); + } + + @TestOnly + public void assertTestProjectsClosed() { + assert ApplicationManager.getApplication().isUnitTestMode(); + if (!myTestProjects.isEmpty()) { + try { + Project project = myTestProjects.iterator().next(); + throw new AssertionError("Test project is not disposed: " + project); + } + finally { + myTestProjects.clear(); + } + } } @Override @@ -993,7 +1001,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt myOpenProjects.remove(project); cacheOpenProjects(); } - myCurrentTestProject = null; + myTestProjects.remove(project); myChangedProjectFiles.remove(project); diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 72a4258cb213..83d230c03b29 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -71,7 +71,7 @@ import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.encoding.EncodingManager; @@ -92,7 +92,6 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.LocalTimeCounter; import com.intellij.util.containers.CollectionFactory; import com.intellij.util.indexing.FileBasedIndex; -import com.intellij.util.indexing.FileBasedIndexImpl; import com.intellij.util.indexing.IndexableFileSet; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; @@ -234,7 +233,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da throw new RuntimeException(e); } - ((FileBasedIndexImpl)FileBasedIndex.getInstance()).registerIndexableSet(new IndexableFileSet() { + FileBasedIndex.getInstance().registerIndexableSet(new IndexableFileSet() { @Override public boolean isInSet(@NotNull final VirtualFile file) { return ourSourceRoot != null && file.getFileSystem() == ourSourceRoot.getFileSystem() && ourProject.isOpen(); @@ -335,7 +334,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da ((ProjectImpl)ourProject).setTemporarilyDisposed(false); ProjectManagerEx projectManagerEx = ProjectManagerEx.getInstanceEx(); - projectManagerEx.setCurrentTestProject(ourProject); + projectManagerEx.openTestProject(ourProject); ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(getProject())).clearUncommitedDocuments(); @@ -404,8 +403,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da catch (Exception e) { } - assertTrue("open: "+getProject().isOpen()+"; disposed:"+getProject().isDisposed()+"; startup passed:"+ passed+"; testProjectIsOurProject:"+(getProject() == projectManagerEx - .getCurrentTestProject())+"; all open projects: "+ + assertTrue("open: "+getProject().isOpen()+"; disposed:"+getProject().isDisposed()+"; startup passed:"+ passed+"; all open projects: "+ Arrays.asList(ProjectManager.getInstance().getOpenProjects()), getProject().isInitialized()); CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(new CodeStyleSettings()); @@ -461,7 +459,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } } - public static void doTearDown(final Project project, IdeaTestApplication application, boolean checkForEditors) throws Exception { + public static void doTearDown(@NotNull final Project project, IdeaTestApplication application, boolean checkForEditors) throws Exception { DocumentCommitThread.getInstance().clearQueue(); CodeStyleSettingsManager.getInstance(project).dropTemporarySettings(); checkAllTimersAreDisposed(); @@ -526,7 +524,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da TemplateDataLanguageMappings.getInstance(project).cleanupForNextTest(); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(null); + ProjectManagerEx.getInstanceEx().closeTestProject(project); application.setDataProvider(null); ourTestCase = null; ((PsiManagerImpl)PsiManager.getInstance(project)).cleanupForNextTest(); @@ -705,7 +703,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da ApplicationManager.getApplication().assertWriteAccessAllowed(); ((ProjectImpl)ourProject).setTemporarilyDisposed(false); final VirtualFile projFile = ((ProjectEx)ourProject).getStateStore().getProjectFile(); - final File projectFile = projFile == null ? null : VfsUtil.virtualToIoFile(projFile); + final File projectFile = projFile == null ? null : VfsUtilCore.virtualToIoFile(projFile); if (!ourProject.isDisposed()) Disposer.dispose(ourProject); if (projectFile != null) { diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 354c47885495..797d9063ca27 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -44,6 +44,7 @@ import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.impl.ModuleManagerImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectManagerEx; +import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.openapi.project.impl.TooManyProjectLeakedException; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModifiableRootModel; @@ -180,11 +181,11 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro myThreadTracker = new ThreadTracker(); setUpProject(); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); storeSettings(); ourTestCase = this; if (myProject != null) { + ProjectManagerEx.getInstanceEx().openTestProject(myProject); CodeStyleSettingsManager.getInstance(myProject).setTemporarySettings(new CodeStyleSettings()); ((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).pushInjectors(); } @@ -212,7 +213,7 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro File projectFile = getIprFile(); myProject = createProject(projectFile, getClass().getName() + "." + getName()); - myProjectManager.setCurrentTestProject(myProject); + myProjectManager.openTestProject(myProject); LocalFileSystem.getInstance().refreshIoFiles(myFilesToDelete); setUpModule(); @@ -482,8 +483,9 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro public void run() { Disposer.dispose(myProject); ProjectManagerEx projectManager = ProjectManagerEx.getInstanceEx(); - if (projectManager != null) { - projectManager.setCurrentTestProject(null); + if (projectManager instanceof ProjectManagerImpl) { + projectManager.closeTestProject(myProject); + ((ProjectManagerImpl)projectManager).assertTestProjectsClosed(); } } }); diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java index 2b8d9be8c609..dcc3571cc2eb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java @@ -162,7 +162,7 @@ class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixtu sm.startCacheUpdate(); sm.runPostStartupActivities(); - ProjectManagerEx.getInstanceEx().setCurrentTestProject(myProject); + ProjectManagerEx.getInstanceEx().openTestProject(myProject); ((PsiDocumentManagerImpl)PsiDocumentManager.getInstance(myProject)).clearUncommitedDocuments(); } }.execute().throwException(); From e9154731723b34eef63aaa970331e05e9cfbf4d2 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 30 May 2012 19:11:18 +0400 Subject: [PATCH 058/239] cleanup --- .../projectWizard/ExistingModuleLoader.java | 2 +- .../ide/util/projectWizard/ModuleBuilder.java | 32 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ExistingModuleLoader.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ExistingModuleLoader.java index cc651af9fbcf..a57c8a6e0877 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ExistingModuleLoader.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ExistingModuleLoader.java @@ -51,7 +51,7 @@ public class ExistingModuleLoader extends ModuleBuilder { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.projectWizard.ExistingModuleLoader"); @NotNull - public Module createModule(ModifiableModuleModel moduleModel) + public Module createModule(@NotNull ModifiableModuleModel moduleModel) throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException { LOG.assertTrue(getName() != null); diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java index 97e7ed4e17a5..3ca4caeb6121 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java @@ -155,7 +155,7 @@ public abstract class ModuleBuilder extends ProjectBuilder{ } @NotNull - public Module createModule(ModifiableModuleModel moduleModel) + public Module createModule(@NotNull ModifiableModuleModel moduleModel) throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException { LOG.assertTrue(myName != null); LOG.assertTrue(myModuleFilePath != null); @@ -182,26 +182,24 @@ public abstract class ModuleBuilder extends ProjectBuilder{ public abstract ModuleType getModuleType(); @NotNull - public Module createAndCommitIfNeeded(final Project project, ModifiableModuleModel model, boolean runFromProjectWizard) throws - InvalidDataException, - ConfigurationException, - IOException, - JDOMException, - ModuleWithNameAlreadyExists{ + public Module createAndCommitIfNeeded(@NotNull Project project, @Nullable ModifiableModuleModel model, boolean runFromProjectWizard) + throws InvalidDataException, ConfigurationException, IOException, JDOMException, ModuleWithNameAlreadyExists { final ModifiableModuleModel moduleModel = model != null ? model : ModuleManager.getInstance(project).getModifiableModel(); final Module module = createModule(moduleModel); if (model == null) moduleModel.commit(); if (runFromProjectWizard) { StartupManager.getInstance(module.getProject()).runWhenProjectIsInitialized(new DumbAwareRunnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - public void run() { - onModuleInitialized(module); - } - }); - } - }); + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + onModuleInitialized(module); + } + }); + } + }); } else { onModuleInitialized(module); @@ -222,13 +220,14 @@ public abstract class ModuleBuilder extends ProjectBuilder{ return true; } + @Override @Nullable public List commit(final Project project, final ModifiableModuleModel model, final ModulesProvider modulesProvider) { final Module module = commitModule(project, model); return module != null ? Collections.singletonList(module) : null; } - public Module commitModule(final Project project, final ModifiableModuleModel model) { + public Module commitModule(@NotNull final Project project, final ModifiableModuleModel model) { final Ref result = new Ref(); if (canCreateModule()) { if (myName == null) { @@ -238,6 +237,7 @@ public abstract class ModuleBuilder extends ProjectBuilder{ myModuleFilePath = project.getBaseDir().getPath() + File.separator + myName + ModuleFileType.DOT_DEFAULT_EXTENSION; } Exception ex = ApplicationManager.getApplication().runWriteAction(new Computable() { + @Override public Exception compute() { try { result.set(createAndCommitIfNeeded(project, model, true)); From f665cf14d70797cfd7d94df8e6f2a8774e62825f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 31 May 2012 15:00:38 +0400 Subject: [PATCH 059/239] test blinking --- .../src/com/intellij/ui/EditorTextField.java | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java index 1731856fc0e5..1721fa49f67b 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java @@ -52,6 +52,7 @@ import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import java.util.ArrayList; +import java.util.List; /** * @author max @@ -67,7 +68,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, private EditorEx myEditor = null; private Component myNextFocusable = null; private boolean myWholeTextSelected = false; - private final ArrayList myDocumentListeners = new ArrayList(); + private final List myDocumentListeners = new ArrayList(); private boolean myIsListenerInstalled = false; private boolean myIsViewer; private boolean myIsSupplementary; @@ -77,12 +78,11 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, private boolean myEnsureWillComputePreferredSize; private Dimension myPassivePreferredSize; private CharSequence myHintText; - private boolean myPaintSelection; private boolean myIsRendererWithSelection = false; private Color myRendererBg; private Color myRendererFg; private int myPreferredWidth = -1; - private ArrayList mySettingsProviders = new ArrayList(); + private final List mySettingsProviders = new ArrayList(); public EditorTextField() { this(""); @@ -116,10 +116,12 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, setFocusable(true); // dsl: this is a weird way of doing things.... addFocusListener(new FocusListener() { + @Override public void focusGained(FocusEvent e) { requestFocus(); } + @Override public void focusLost(FocusEvent e) { } }); @@ -146,6 +148,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, setDocument(myDocument); // reinit editor. } + @Override public String getText() { return myDocument.getText(); } @@ -159,6 +162,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } } + @Override public JComponent getComponent() { return this; } @@ -173,12 +177,14 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, uninstallDocumentListener(false); } + @Override public void beforeDocumentChange(DocumentEvent event) { for (DocumentListener documentListener : myDocumentListeners) { documentListener.beforeDocumentChange(event); } } + @Override public void documentChanged(DocumentEvent event) { for (DocumentListener documentListener : myDocumentListeners) { documentListener.documentChanged(event); @@ -189,6 +195,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, return myProject; } + @Override public Document getDocument() { return myDocument; } @@ -241,8 +248,10 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, public void setText(final String text) { ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override public void run() { CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override public void run() { myDocument.replaceString(0, myDocument.getTextLength(), text); if (myEditor != null) { @@ -293,6 +302,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, return myEditor.getCaretModel(); } + @Override public boolean isFocusOwner() { if (myEditor != null) { return IJSwingUtilities.hasFocus(myEditor.getContentComponent()); @@ -311,6 +321,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, remove(editor.getComponent()); final Application application = ApplicationManager.getApplication(); final Runnable runnable = new Runnable() { + @Override public void run() { if (!editor.isDisposed()) { EditorFactory.getInstance().releaseEditor(editor); @@ -325,6 +336,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } } + @Override public void addNotify() { releaseEditor(); @@ -350,6 +362,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, add(component, BorderLayout.CENTER); } + @Override public void removeNotify() { super.removeNotify(); releaseEditor(); @@ -374,6 +387,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, }); } + @Override public void setFont(Font font) { super.setFont(font); if (myEditor != null) { @@ -443,15 +457,11 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, final EditorFactory factory = EditorFactory.getInstance(); EditorEx editor; - if (!myIsViewer) { - editor = myProject != null - ? (EditorEx)factory.createEditor(myDocument, myProject) - : (EditorEx)factory.createEditor(myDocument); + if (myIsViewer) { + editor = myProject == null ? (EditorEx)factory.createViewer(myDocument) : (EditorEx)factory.createViewer(myDocument, myProject); } else { - editor = myProject != null - ? (EditorEx)factory.createViewer(myDocument, myProject) - : (EditorEx)factory.createViewer(myDocument); + editor = myProject == null ? (EditorEx)factory.createEditor(myDocument) : (EditorEx)factory.createEditor(myDocument, myProject); } final EditorSettings settings = editor.getSettings(); @@ -539,8 +549,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, protected void updateBorder(@NotNull final EditorEx editor) { if (editor.isOneLineMode() - && (!Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor")) - && (SwingUtilities.getAncestorOfClass(JTable.class, this) == null || Boolean.TRUE.equals(getClientProperty("JBListTable.isTableCellEditor"))))) { + && !Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor")) + && (SwingUtilities.getAncestorOfClass(JTable.class, this) == null || Boolean.TRUE.equals(getClientProperty("JBListTable.isTableCellEditor")))) { final Container parent = getParent(); if (parent instanceof JTable || parent instanceof CellRendererPane) return; @@ -575,6 +585,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, return true; } + @Override public void setEnabled(boolean enabled) { if (isEnabled() != enabled) { super.setEnabled(enabled); @@ -606,6 +617,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, super.addImpl(comp, constraints, index); } + @Override public Dimension getPreferredSize() { if (super.isPreferredSizeSet()) { return super.getPreferredSize(); @@ -668,12 +680,14 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, myPreferredWidth = preferredWidth; } + @Override public Component getNextFocusableComponent() { if (myEditor == null && myNextFocusable == null) return super.getNextFocusableComponent(); if (myEditor == null) return myNextFocusable; return myEditor.getContentComponent().getNextFocusableComponent(); } + @Override public void setNextFocusableComponent(Component aComponent) { if (myEditor != null) { myEditor.getContentComponent().setNextFocusableComponent(aComponent); @@ -683,13 +697,15 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } + @Override protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { - if (e.isConsumed() || (myEditor != null && !myEditor.processKeyTyped(e))) { + if (e.isConsumed() || myEditor != null && !myEditor.processKeyTyped(e)) { return super.processKeyBinding(ks, e, condition, pressed); } return true; } + @Override public void requestFocus() { if (myEditor != null) { myEditor.getContentComponent().requestFocus(); @@ -700,6 +716,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } } + @Override public boolean requestFocusInWindow() { if (myEditor != null) { final boolean b = myEditor.getContentComponent().requestFocusInWindow(); @@ -726,6 +743,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, return myEditor == null ? this : myEditor.getContentComponent(); } + @Override public Object getData(String dataId) { if (myEditor != null && myEditor.isRendererMode()) return null; @@ -745,10 +763,6 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, myEnsureWillComputePreferredSize = true; } - public void setPaintSelection(boolean b) { - myPaintSelection = b; - } - public void setAsRendererWithSelection(Color backgroundColor, Color foregroundColor) { myIsRendererWithSelection = true; myRendererBg = backgroundColor; From 12c13555a81794f658a19cff5fa250ef09c9e50a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 31 May 2012 15:24:52 +0400 Subject: [PATCH 060/239] diagnostics --- .../navigation/JavaMethodNavigationOffsetProvider.java | 1 + .../com/intellij/codeInsight/navigation/MethodUpDownUtil.java | 4 +++- .../navigation/XmlMethodNavigationOffsetProvider.java | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java index 62d7bc1b2b03..ee84ce5c6c4a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java @@ -24,6 +24,7 @@ import java.util.ArrayList; * @author yole */ public class JavaMethodNavigationOffsetProvider implements MethodNavigationOffsetProvider { + @Override @Nullable public int[] getMethodNavigationOffsets(final PsiFile file, final int caretOffset) { if (file instanceof PsiJavaFile) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpDownUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpDownUtil.java index e52cd1698496..a4b2e80d854c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpDownUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpDownUtil.java @@ -51,7 +51,9 @@ public class MethodUpDownUtil { public static int[] offsetsFromElements(final Collection array) { TIntArrayList offsets = new TIntArrayList(array.size()); for (PsiElement element : array) { - offsets.add(element.getTextOffset()); + int offset = element.getTextOffset(); + assert offset >= 0 : element + "; offset: " + offset; + offsets.add(offset); } offsets.sort(); return offsets.toNativeArray(); diff --git a/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java b/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java index d7eb4a73a1e0..136ddf84a97e 100644 --- a/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java +++ b/xml/impl/src/com/intellij/codeInsight/navigation/XmlMethodNavigationOffsetProvider.java @@ -27,6 +27,7 @@ import java.util.ArrayList; * @author yole */ public class XmlMethodNavigationOffsetProvider implements MethodNavigationOffsetProvider { + @Override public int[] getMethodNavigationOffsets(final PsiFile file, final int caretOffset) { if (file instanceof XmlFile) { PsiElement element = file; From a8ffbd11ddd3848635f5ea76f0e0cce40877ca35 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 1 Jun 2012 12:40:12 +0400 Subject: [PATCH 061/239] disabled dangerous test --- .../testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java index 0d65d499a8dd..07f23d257541 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java @@ -351,7 +351,7 @@ public class FileWatcherTest extends PlatformLangTestCase { } */ - public void testSubst() throws Exception { + public void _testSubst() throws Exception { if (!SystemInfo.isWindows) { System.out.println("Ignored: Windows required"); return; From 6455992412155c9676f97bd7232f5a95124f8d6a Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 11:35:19 +0400 Subject: [PATCH 062/239] inapplicable args in translating to java --- .../refactoring/convertToJava/ArgumentListGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java index 8620f5902d26..3f1010dd1b86 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.refactoring.convertToJava; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NullUtils; import com.intellij.psi.PsiArrayType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiSubstitutor; @@ -63,7 +64,7 @@ class ArgumentListGenerator { } final PsiSubstitutor substitutor = signature == null ? PsiSubstitutor.EMPTY : signature.getSubstitutor(); - if (argInfos == null) { + if (argInfos == null || NullUtils.hasNull(argInfos)) { generateSimple(exprs, namedArgs, clArgs, context, substitutor); return; } From df010c3a33f2fd883591c5bcc60e24aa6db18de9 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 11:50:27 +0400 Subject: [PATCH 063/239] semicolon in enum with no constants --- .../groovy/refactoring/convertToJava/ClassGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java index ceda991f2c1d..b950b4cc9486 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassGenerator.java @@ -118,8 +118,9 @@ public class ClassGenerator { } if (enumConstants.length > 0) { //text.removeFromTheEnd(1).append(";\n"); - text.delete(text.length()-1, text.length()).append(";\n"); + text.delete(text.length() - 1, text.length()); } + text.append(";\n"); } writeAllMethods(text, classItemGenerator.collectMethods(typeDefinition, isClassDef), typeDefinition); From 1d6b4274946b027ace52e427ce9ad4503c8a8b70 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 12:28:03 +0400 Subject: [PATCH 064/239] fix testdata --- .../testdata/refactoring/convertGroovyToJava/file/hash.groovy | 1 + .../testdata/refactoring/convertGroovyToJava/file/hash.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.groovy index aee07196dbe0..1e7d79bd2cba 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.groovy +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.groovy @@ -1,5 +1,6 @@ class BigInteger { BigInteger(int i, byte[] arr) {} + String toString(int radix) {""} } class NoSuchAlgorithmException extends Exception {} diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java index e7b10c48e8bc..a333176b0dd7 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java @@ -1,6 +1,10 @@ public class BigInteger extends groovy.lang.GroovyObjectSupport implements groovy.lang.GroovyObject { public BigInteger(int i, java.lang.Byte[] arr) { } +public java.lang.String toString(int radix) { +return ""; +} + } public class NoSuchAlgorithmException extends java.lang.Exception implements groovy.lang.GroovyObject { } From 1376176e46a17d8e5b5a73796d48b47e3c4b7d75 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 12:32:13 +0400 Subject: [PATCH 065/239] asserts --- .../completion/GroovyCompletionTest.groovy | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 42bf94b12d2f..2a835f46e23e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -908,7 +908,7 @@ class Fopppp { class Instantiation {} ''' myFixture.completeBasic() - assert myFixture.lookupElementStrings[0] == 'instanceof' + assertEquals 'instanceof', myFixture.lookupElementStrings[0] } public void testForFinal() { @@ -1003,7 +1003,7 @@ while(true) { myFixture.configureByText "a.groovy", "def foo(stryng) { println str }" myFixture.completeBasic() - assert myFixture.lookupElementStrings[0] == 'stryng' + assertEquals 'stryng', myFixture.lookupElementStrings[0] } private def caseSensitiveNone() { @@ -1077,13 +1077,13 @@ class X { public void testInitializerMatters() throws Exception { myFixture.configureByText("a.groovy", "class Foo {{ String fx = getFoo(); }; String getFoo() {}; }"); myFixture.completeBasic() - assert myFixture.lookupElementStrings == ["foo"] + assertOrderedEquals(myFixture.lookupElementStrings, ["foo"]) } public void testFieldInitializerMatters() throws Exception { myFixture.configureByText("a.groovy", "class Foo { String fx = getFoo(); String getFoo() {}; }"); myFixture.completeBasic() - assert myFixture.lookupElementStrings == ["foo"] + assertOrderedEquals(myFixture.lookupElementStrings, ["foo"]) } public void testAccessStaticViaInstanceSecond() throws Exception { @@ -1096,7 +1096,7 @@ public class KeyVO { myFixture.complete(CompletionType.BASIC, 1) assert !myFixture.lookupElementStrings myFixture.complete(CompletionType.BASIC, 2) - assert myFixture.lookupElementStrings == ["foo"] + assertOrderedEquals(myFixture.lookupElementStrings, ["foo"]) } public void testNoRepeatingModifiers() { @@ -1118,11 +1118,11 @@ public class KeyVO { myFixture.addClass("package bar; public class Util { public static void bar() {} }") myFixture.configureByText 'a.groovy', 'Util.' myFixture.completeBasic() - assert myFixture.lookupElementStrings[0..1] == ['Util.bar', 'Util.foo'] + assertOrderedEquals myFixture.lookupElementStrings[0..1] , ['Util.bar', 'Util.foo'] def presentation = LookupElementPresentation.renderElement(myFixture.lookupElements[0]) - assert 'Util.bar' == presentation.itemText - assert '() (bar)' == presentation.tailText + assertEquals 'Util.bar', presentation.itemText + assertEquals '() (bar)', presentation.tailText assert !presentation.tailGrayed myFixture.type 'f\n' From f945ba6c99fb12ed91d6280047c7caa72eae1127 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 12:36:03 +0400 Subject: [PATCH 066/239] skip temp classes in resolve --- .../groovy/lang/psi/GroovyPsiElementFactory.java | 2 +- .../impl/statements/GrConstructorInvocationImpl.java | 10 ++-------- .../plugins/groovy/lang/psi/util/PsiUtil.java | 10 +++++++++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java index eb0128dacecb..4c9e7f7037c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyPsiElementFactory.java @@ -54,7 +54,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; */ public abstract class GroovyPsiElementFactory implements JVMElementFactory { - @NonNls public static final String DUMMY_FILE_NAME = "DUMMY__"; + @NonNls public static final String DUMMY_FILE_NAME = "DUMMY__1234567890_DUMMYYYYYY___"; public abstract GrCodeReferenceElement createCodeReferenceElementFromClass(PsiClass aClass); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java index e6c630bef390..be38a735e959 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements; import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.tree.TokenSet; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +27,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisSuperReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrCallImpl; @@ -78,7 +76,7 @@ public class GrConstructorInvocationImpl extends GrCallImpl implements GrConstru if (isThisCall()) { substitutor = PsiSubstitutor.EMPTY; } else { - GrTypeDefinition enclosing = getEnclosingClass(); + PsiClass enclosing = PsiUtil.getContextClass(this); assert enclosing != null; substitutor = TypeConversionUtil.getSuperClassSubstitutor(clazz, enclosing, PsiSubstitutor.EMPTY); } @@ -110,17 +108,13 @@ public class GrConstructorInvocationImpl extends GrCallImpl implements GrConstru @Nullable public PsiClass getDelegatedClass() { - GrTypeDefinition typeDefinition = getEnclosingClass(); + PsiClass typeDefinition = PsiUtil.getContextClass(this); if (typeDefinition != null) { return isThisCall() ? typeDefinition : typeDefinition.getSuperClass(); } return null; } - private GrTypeDefinition getEnclosingClass() { - return PsiTreeUtil.getParentOfType(this, GrTypeDefinition.class); - } - @NotNull public String getCanonicalText() { return getText(); //TODO diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 1c920224e894..7f5c771938c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -570,7 +570,7 @@ public class PsiUtil { @Nullable public static PsiClass getContextClass(PsiElement context) { while (context != null) { - if (context instanceof PsiClass) { + if (context instanceof PsiClass && !isInDummyFile(context)) { return (PsiClass)context; } else if (context instanceof GroovyFileBase && context.isPhysical()) { @@ -582,6 +582,14 @@ public class PsiUtil { return null; } + private static boolean isInDummyFile(PsiElement context) { + PsiFile file = context.getContainingFile(); + if (file == null) return false; + + String name = file.getName(); + return name.startsWith(GroovyPsiElementFactory.DUMMY_FILE_NAME); + } + @Nullable public static GroovyPsiElement getFileOrClassContext(PsiElement context) { while (context != null) { From 2a014c660b71443a9fe1b80942c2bd4c05f9ee73 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 1 Jun 2012 12:53:15 +0400 Subject: [PATCH 067/239] moving xml-tests to community: getting rid of ultimate dependencies --- .../intellij/psi/AbstractReparseTestCase.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 java/testFramework/src/com/intellij/psi/AbstractReparseTestCase.java diff --git a/java/testFramework/src/com/intellij/psi/AbstractReparseTestCase.java b/java/testFramework/src/com/intellij/psi/AbstractReparseTestCase.java new file mode 100644 index 000000000000..43bf6ccc20ec --- /dev/null +++ b/java/testFramework/src/com/intellij/psi/AbstractReparseTestCase.java @@ -0,0 +1,105 @@ +package com.intellij.psi; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.text.BlockSupport; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; + +/** + * @author maxim + */ +public abstract class AbstractReparseTestCase extends PsiTestCase { + protected FileType myFileType; + protected PsiFile myDummyFile; + private int myInsertOffset; + + protected void setFileType(final FileType fileType) { + myFileType = fileType; + } + + protected void insert(@NonNls final String s) throws IncorrectOperationException { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + String oldText = myDummyFile.getText(); + String expectedNewText = oldText.substring(0, myInsertOffset) + s + oldText.substring(myInsertOffset); + + try { + doReparse(s, expectedNewText, 0); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + myInsertOffset += s.length(); + } + }); + } + }, "asd", null); + } + + protected void moveEditPointLeft(int count) { + myInsertOffset -= count; + } + + protected void moveEditPointRight(int count) { + myInsertOffset += count; + } + + protected void setEditPoint(int pos) { + myInsertOffset = pos; + } + + protected void remove(int count) throws IncorrectOperationException { + String oldText = myDummyFile.getText(); + String expectedNewText = oldText.substring(0, myInsertOffset-count) + oldText.substring(myInsertOffset); + + doReparse("", expectedNewText, count); + myInsertOffset -= count; + } + + protected void doReparse(final String s, final String expectedNewText, final int length) throws IncorrectOperationException { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + BlockSupport blockSupport = ServiceManager.getService(myProject, BlockSupport.class); + try { + blockSupport.reparseRange(myDummyFile, myInsertOffset - length, myInsertOffset, s); + String foundStructure = DebugUtil.treeToString(SourceTreeToPsiMap.psiElementToTree(myDummyFile), false); + final PsiFile psiFile = createDummyFile(getName() + "." + myFileType.getDefaultExtension(), expectedNewText); + String expectedStructure = DebugUtil.treeToString(SourceTreeToPsiMap.psiElementToTree(psiFile), false); + if (!expectedStructure.equals(foundStructure)) { + System.out.println("expected: "); + System.out.println(expectedStructure); + System.out.println("found: "); + System.out.println(foundStructure); + assertEquals(expectedStructure, foundStructure); + } + + assertEquals("Reparse tree should be equal to the document",expectedNewText,myDummyFile.getText()); + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + } + }); + } + }, "asd", null); + } + + protected void prepareFile(@NonNls String prefix, @NonNls String suffix) throws IncorrectOperationException { + myDummyFile = createDummyFile(getName() + "." + myFileType.getDefaultExtension(), prefix + suffix); + myInsertOffset = prefix.length(); + } +} From fa8670510cff2b8fbea1fdd329f78cfc3c0ba82d Mon Sep 17 00:00:00 2001 From: irengrig Date: Fri, 1 Jun 2012 13:01:35 +0400 Subject: [PATCH 068/239] SVN: use standard configuration directory on Mac and Unix as well --- .../idea/svn/IdeaSubversionConfigurationDirectory.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSubversionConfigurationDirectory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSubversionConfigurationDirectory.java index c9176f2b7961..1947ca03a902 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSubversionConfigurationDirectory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSubversionConfigurationDirectory.java @@ -15,7 +15,6 @@ */ package org.jetbrains.idea.svn; -import com.intellij.openapi.util.SystemInfo; import org.tmatesoft.svn.core.wc.SVNWCUtil; import java.io.File; @@ -26,9 +25,6 @@ public class IdeaSubversionConfigurationDirectory { public static String getPath() { final File standard = SVNWCUtil.getDefaultConfigurationDirectory(); - if (SystemInfo.isWindows) { - return standard.getAbsolutePath(); - } - return standard.getParent() + File.separator + standard.getName() + "_IDEA"; + return standard.getAbsolutePath(); } } From 57c8e750e60e50c50ffbcf4afc4c7e4a3ba1ba54 Mon Sep 17 00:00:00 2001 From: "Maxim.Medvedev" Date: Fri, 1 Jun 2012 12:57:26 +0400 Subject: [PATCH 069/239] diagnostics --- .../org/jetbrains/plugins/groovy/formatter/GroovyBlock.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java index 32184b90452c..8225b524b6c5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyBlock.java @@ -111,6 +111,10 @@ public class GroovyBlock implements Block, GroovyElementTypes, ASTBlock { try { mySubBlocks = new GroovyBlockGenerator(this).generateSubBlocks(); } + catch (AssertionError e) { + final PsiFile file = myNode.getPsi().getContainingFile(); + LogMessageEx.error(LOG, "Formatting failed for file " + file.getName(), file.getText()); + } catch (RuntimeException e) { final PsiFile file = myNode.getPsi().getContainingFile(); LogMessageEx.error(LOG, "Formatting failed for file " + file.getName(), file.getText()); From 6ccb8dd2a31b0e5ba52909e19a46483ca1a5880f Mon Sep 17 00:00:00 2001 From: irengrig Date: Fri, 1 Jun 2012 13:05:45 +0400 Subject: [PATCH 070/239] svnkit 1.7.5 9277 - better logging (does not affect performance) --- plugins/svn4idea/lib/svnkit-javahl.jar | Bin 329668 -> 329668 bytes plugins/svn4idea/lib/svnkit-javahl16.zip | Bin 165836 -> 165836 bytes plugins/svn4idea/lib/svnkit.jar | Bin 3330289 -> 3330582 bytes plugins/svn4idea/lib/svnkitsrc.zip | Bin 2100702 -> 2101279 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/svn4idea/lib/svnkit-javahl.jar b/plugins/svn4idea/lib/svnkit-javahl.jar index 7eee9c01f89018132cfb35a706a142f2fc925ce4..088881d4109923ea0f868362bb26a8d0da81e8e6 100644 GIT binary patch delta 4674 zcmX|Dd0dUz8^7ng=eAhNPE(eQEQJ`<#Mt+-uf>FrtP?RvGnfobBkS)@UVHg5qsWq5 zy%CXalu9a@(n1Xqsgal{{NCqz-p}u^?|HWGvz>F_Yuek&w6|50sS_m8NT;)~(0PRI zZ_>@eBP?;))!B*B`v=XjzAf9>wEM#5;1{+g+qsA5MxSh{=N@5(cztJpB7F}4bF=;c zgUtr1U<@$xXMnZlt0cfhjbC!WDOTGAU~Y@oXus8JG0ILhwP?4uTZ;Of?X58Ga3@=o z6?@PKi8Z&;j@IJwGx?c_Z;<_9t6Bfqz&I+>v)1rx&g37s0XKrTL z`s7QrRrD1|Tiw3|(`LEZOX$0yhPMw=eHZEtVGZEh(%64+7{?T6Cz^EgRhxxjVIHJt zZ?qq_466tkaRqVg=$=^R`Y~omzj?ej!_X8jpB1OoP;bM}W1Qr3mxQIU^Mq)O$(!`b z3_3E+%*Ghm!ymD^=TIxqPhT+?{m!q_n}Zy?&ZdouhI_va2eIYO7&NEt3PPN=HvQp!)pws_%Gr5E9EW=IZI8ssLZ_S8$gn@I zhjDqn50;i)#L)kK$ui^}Qq~XUbx-mTzb)@Zaz!X&qspP^H=()&WP?-9C`jv9a|?!U zaI38c(d8}Olo{^`*Zgaa=1p}qVE+ES8;TJh>aezrZFe0!qSNVeb#OTh;Wd_qhxH2Z z85-U}K*-0T5Ma#s)ExugeSW2iu}@iB5amyd)v2h|aW)JU0|kS3ATJRN9)f&CFn9?{ zzF^a!Y{ki(-2qSKUket3A=?|VLQpJh%&sckifO?lmgSz>g9 z18aw-Hr?4}JY+kvj&xIVCMA@uRYGM%pF#%+*!m%pvlUcy?|vZA6BqUFnwjcFKdg3J$|eSmUMJIGa>ULe};Eg zF8Yxbf$x={SUtKZfefdolx|~7ka*m7)*BA8{|;6QzP>?h0`#SptW+u;0W>3KKjfqKMk%yCU0Ulz9>qwZ~tZ@@{9ru~Mz^K+}J)K!9jz;c)qnQ@Nd#Y6O))?LgFgk`0 z0DK<9zkw88WBF+Kfmgmy=8dt8023d9_a-q-TS3hoJ{rl~GB`e{wwe6eatM0hB5kI( zzTn}*7h~18?kktNNc|Lpn=}XOtQsU8#6$29X&SarI9!^DhaRJ)QZzLgC#^$G-~_1> z538q0=D2kKSyC{45_>!K)Qwa>71o9ivLMw8!C z=?B!5FPDzv;n!8tT|Bt2mhk6Waa}9X&&J0eB>b2wNgJgNI0?5+(m-6%`pr@nMveJd zYK6?6zew%yupvlF#2+n}y;4&sSsooK4T0J02$e=Pg+uy(rBTS&{FL;zHE1lZNP{tY z>@_K!+Pe@?RF|%9afSr#sW&ZIYNpIclGKlr8qhaca;A@%@9+U%-d5-QyBYcQ`6SvZ z5h)V=PW+fE^~YI6XG(3b;X;cKl#%B-S`duT9=q3^g7*CdCFShqL_R{ zYxF2wDYOl(7B*PtsI`JFYx9j_DQW@&L?j*@wutq3I2tJ0;~`^UWzKqDud76bnOA5pG5Eq(&+h6sUo-to4ulT8uA7L=tCVg#T=q!W{ydNo+ z01i4M)&QP6BUS<0o)w;eo6d^)fCU=5MG1G1{}UxV04t-!GQipA#2morb7C%F)AM36 z;M((I9$@x);SK0|K`aD3e1YP`MX?fOzl*{Lu;3!;M@Cb8L^SbAmneSuC6Y~-$iJsi zd=GI)jKUAlDu(3EF;sVP4AturOZD!H6;r^kG?w}s8b|dVj}za4zCKQP0nSrsK1mAM zJH=D}pm@^1h^PG1FN+1>Z@f%?Ev^vyU7`HhSIEyTf%3@-RDX?zldh6I_A14-x<+{d zuF)JHTqAzhMA9EiB)^74s>AC#*^{mlPmdd7I@GiI2JP|X4bsm@qB-A4qWL=BB>ep* z?Z5t}SOIZMlPOQ8hW$(w7jB~a(ISQB8<;}86)BX*{T9V1-y%Ns^0@+^dhhJyt+z#2 z5KiBw%U5$-%m(?}RBGaUDhO@-*!8oa7J7BK1+ zJ-aWeXdc_Di1&FFy_6}{gmKk07u$cRzkq+J?;;I{ye2tZLtaC&w}!Vg?EZ%IJ2kA- zaB?l_FV@mMYyOsSt%kW8_J2qEPz~Q{=>9M1<2AIYqkaPGsQ%}5^z$?8JJ-ml>s4QG8Ky`rJbXOe&X zOnFN`W4)mx^ziiz{S!fM#0Y&g%+b(=lm0N*<45nKhF%iM$r^SQB>$#irG``Vq`#zL YYcoB5?6#Zf@#9)yrpGR4n(Np64?~Re)Bpeg delta 4674 zcmX|Dd0fx;AOF6OZ{;d?S~)T~3Nd6c_dWN`7D8?!=4!(-%-r@}K5qH3DRSgneWHo< zjZ&n@P>vcBsmZY@?EQMZK9ApD&)0pwKi{uyYi--s+Es@Q6tc3(jQp)SEQ?`@MmID=FTg%$M%K?rljt#PzCMunSWpXy8sBd-e zJ`=0h*z+u6zdkLo%Ef){F#L)E0SsM}{in}9qFe(kKlb&~j-Qs5tc?dop-=YU7k1E* zZB!=uXycY4*6{1*2=WoLzu{`G))RBh_JA>qTI#$Tqh;kIPc2MWlR6O53R7N-?2lOQR2gE;=pc-_ zHg*xbSWd>5-#}H9@WdsNLT z#Isbq1&56vx`Bf={bO@$LG&i=a!|pH)qYX?&-3M?%j&5N3%2D%%d@cdN`cb z$55X}umx~5deFCQEUZ?)GKKX-m16*V2Fujn&t}VE`ugHP=8VLaAXXJi+Pj$9F!GdT z3~yJ<{hsB5?b#n#IhyDp45z2(t!C3OaQ`)|H4xgewd^(62CicRF-rV;W~PVxMQHlW z#_CNcGA-&T`&{$7DV<_BFnnWr>y4}kBe`v6&9Ugdzp>jGp^?UF!$oR7dl@WU_uR*t zpzW~z>>$NnyR1`}F)H>%u7w1u*sJz4d%Z;%n~QeZL6(W3W*=q)kcjz1l?gGAMbN^3 zKguFuXxd0CtAHfKqnR5vJ3o#kKziLffrVkX%=7Fgn3*;vi9G_%S2iX>?m^(8C{Lv?=13Lrw0 zQc9*rykUc}pt5)D7hKs-AJ`J?ru-Azi^ML@r=seknWvy6#esi;MORef3|IfjiQ`9F zFRj62P!&;&Ct=ROI=l#S`qkyMl?~2(H^yt~$^+1LlN-m+gy!9l-ve96M%*3CYTJa5 zMq+()?u5jymfV@vGu>~^)FbLyIx%fqW!0*G6JAX#ZpGtN1TDNZf2p3BzQ>#Is|7@- zUff*(F`=)j2Z(_KxGzf94dN$}=s1iYLRIbvo+iO2Vk~a}PgYMI$B(1UGCzK$El7HA z;nUGLavN`ks%#72f|6-F_(nHJSM|FRKcsqNU@f}JEW{Les{5)4&Lt^ZFp+4U#L&t?eeKr*F;X9#z%oUNiR4l>1 zeV2<)xT3`?LVU-ItmuN?{mzLrYVTxlZdsbz;z$AQsY^=|)%B5yLj5=?hqg(=o8uS)dvy5x zvYPX6c4XJ)qjc88lZE1~4P7XGblY@U2Q6~uNMl3ur3=>Cd!eLbt+7E%F+g-rphbVd3X?$w??_uum4F z#4${IprpegITpvV<*@X^4_f>Y+2Q~H5w)@-@&`2yZArMqoA09+6urvToJkkbG=AC(ILj~|tD0bP$tKfvY3Q;T1{3FiDNnme1Lv}UK5(b^6xn-UuJKuQ9 zr^QqKr3McElk_ovl3(p}lqdKc&GFVbir+DTREAt z_W1k)$wwyAoG&EOd_6A`{&tb}Uw%=}2EQ3el;^5}?QG;1W~2M4nN0HyNv61k$&_d8 zCGtauJK!H-;~<14)^#{mCz3N>*eg@#fom71HGDo2CPN!a4U8S9Fy-K%NdX;uD>>7nRevQJ~ zWl*^38Kk#mkYCg5R9?t+y2&TkY3BVh$^URBwc(IOI5&&(WMq+Dn;R5w%MFTOe1mSW z|4s7${U+tH&nEvl*(6WNrZF|TMdMg{i{fM(*zPZ?d(&TXJbngt5AZ0_9vqW(HF2As zd%xRMLilY;$?s5U)9z497w%AsdUuImbXSgq$*0_<5^9|+ zUqLRF()}K_7yiQ{p!o_{6{-g(TlwsOnet=4ZtFKU4EiyzQB)OQGj;Rgc2W z&($0i=08{aQTSC6$qy9CPQd3BN%&ROTwlmufc`J!*MN~P)U#9gS+Saj!qvqT_h~Ub zzo8|Bu_bCQO7HrQ>Q7a)RnwO1uy z`JU#Q|6UFPzD>Cd1Pm*e@J~&vQbBfeDyYt@26}%We!GFM3>^KDZOQI)_5zJ_ns&lXgtBjubgET~bm)N^*vj^bzS< rk`W(@J{B=fR@^V$c)0a2b*cdXVB;Uo diff --git a/plugins/svn4idea/lib/svnkit.jar b/plugins/svn4idea/lib/svnkit.jar index bcfbd9ed6c8e8ed9fb81d6d2e249d9461fe55f57..4d6c54ac72439f9bf0f40e1f85bbcb6b28e1d39d 100644 GIT binary patch delta 129297 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%0AG6S+ZjdJsc>86KtGQnG9epNqLyTg1;gC2 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 delta 129028 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ΠJyA6tP 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≈_k>C2+eh0EnmQJ(?Xqj? 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 ZI~R(K52(5cvH>Oz5(hooB|-Qt>VHbQhW`Kn From ed59b0029140900054d29866c994d1c42aa3fcb3 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 1 Jun 2012 13:39:37 +0400 Subject: [PATCH 071/239] IDEA-86868 --- .../com/intellij/designer/designSurface/QuickFixManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/QuickFixManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/QuickFixManager.java index 8ff91ee66a96..f57f100283e4 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/QuickFixManager.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/QuickFixManager.java @@ -54,7 +54,9 @@ public final class QuickFixManager extends AbstractQuickFixManager implements Co protected Rectangle getErrorBounds() { List selection = myDesigner.getSurfaceArea().getSelection(); if (selection.size() == 1) { - return selection.get(0).getBounds(myComponent); + Rectangle bounds = selection.get(0).getBounds(myComponent); + bounds.x -= ICON.getIconWidth() - 5; + return bounds; } return null; From e892087bbe82a8b2d3a0af979a12e68e82face75 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 24 May 2012 16:45:29 +0200 Subject: [PATCH 072/239] refactoring to make the code easier to reuse externally --- .../codeInsight/daemon/impl/MarkerType.java | 240 ++++++++++-------- 1 file changed, 134 insertions(+), 106 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index b12ab5e29c81..392325af383f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -42,6 +42,7 @@ import com.intellij.util.*; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; @@ -56,22 +57,7 @@ public class MarkerType { if (!(parent instanceof PsiMethod)) return null; PsiMethod method = (PsiMethod)parent; - PsiMethod[] superMethods = method.findSuperMethods(false); - if (superMethods.length == 0) return null; - - PsiMethod superMethod = superMethods[0]; - boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); - boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT); - - final boolean sameSignature = superMethod.getSignature(PsiSubstitutor.EMPTY).equals(method.getSignature(PsiSubstitutor.EMPTY)); - @NonNls final String key; - if (isSuperAbstract && !isAbstract){ - key = sameSignature ? "method.implements" : "method.implements.in"; - } - else{ - key = sameSignature ? "method.overrides" : "method.overrides.in"; - } - return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key)); + return calculateOverridingMethodTooltip(method); } }, new LineMarkerNavigator(){ @Override @@ -79,15 +65,40 @@ public class MarkerType { PsiElement parent = element.getParent(); if (!(parent instanceof PsiMethod)) return; PsiMethod method = (PsiMethod)parent; - PsiMethod[] superMethods = method.findSuperMethods(false); - if (superMethods.length == 0) return; - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); - PsiElementListNavigator.openTargets(e, superMethods, - DaemonBundle.message("navigation.title.super.method", method.getName()), - new MethodCellRenderer(showMethodNames)); + navigateToOverridingMethod(e, method); } }); + + @Nullable + public static String calculateOverridingMethodTooltip(PsiMethod method) { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) return null; + + PsiMethod superMethod = superMethods[0]; + boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); + boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT); + + final boolean sameSignature = superMethod.getSignature(PsiSubstitutor.EMPTY).equals(method.getSignature(PsiSubstitutor.EMPTY)); + @NonNls final String key; + if (isSuperAbstract && !isAbstract){ + key = sameSignature ? "method.implements" : "method.implements.in"; + } + else{ + key = sameSignature ? "method.overrides" : "method.overrides.in"; + } + return GutterIconTooltipHelper.composeText(superMethods, "", DaemonBundle.message(key)); + } + + public static void navigateToOverridingMethod(MouseEvent e, PsiMethod method) { + PsiMethod[] superMethods = method.findSuperMethods(false); + if (superMethods.length == 0) return; + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods); + PsiElementListNavigator.openTargets(e, superMethods, + DaemonBundle.message("navigation.title.super.method", method.getName()), + new MethodCellRenderer(showMethodNames)); + } + public static final String SEARCHING_FOR_OVERRIDING_METHODS = "Searching for overriding methods"; public static final MarkerType OVERRIDEN_METHOD = new MarkerType(new NullableFunction() { @Override @@ -96,57 +107,66 @@ public class MarkerType { if (!(parent instanceof PsiMethod)) return null; PsiMethod method = (PsiMethod)parent; - PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); - OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); - - boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); - - if (processor.isOverflow()){ - return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); - } - - PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]); - if (overridings.length == 0) return null; - - Comparator comparator = new MethodCellRenderer(false).getComparator(); - Arrays.sort(overridings, comparator); - - String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header"); - @NonNls String pattern = "    {1}"; - return GutterIconTooltipHelper.composeText(overridings, start, pattern); + return getOverriddenMethodTooltip(method); } }, new LineMarkerNavigator(){ @Override public void browse(MouseEvent e, PsiElement element) { PsiElement parent = element.getParent(); if (!(parent instanceof PsiMethod)) return; - if (DumbService.isDumb(element.getProject())) { - DumbService.getInstance(element.getProject()).showDumbModeNotification("Navigation to overriding classes is not possible during index update"); - return; - } - - final PsiMethod method = (PsiMethod)parent; - final PsiElementProcessor.CollectElementsWithLimit collectProcessor = - new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); - } - }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { - return; - } - - PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); - if (overridings.length == 0) return; - boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings); - MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames); - Arrays.sort(overridings, renderer.getComparator()); - final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); - PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater); + navigateToOverriddenMethod(e, (PsiMethod)parent); } }); + + public static String getOverriddenMethodTooltip(PsiMethod method) { + PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5); + OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(processor)); + + boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); + + if (processor.isOverflow()){ + return isAbstract ? DaemonBundle.message("method.is.implemented.too.many") : DaemonBundle.message("method.is.overridden.too.many"); + } + + PsiMethod[] overridings = processor.toArray(new PsiMethod[processor.getCollection().size()]); + if (overridings.length == 0) return null; + + Comparator comparator = new MethodCellRenderer(false).getComparator(); + Arrays.sort(overridings, comparator); + + String start = isAbstract ? DaemonBundle.message("method.is.implemented.header") : DaemonBundle.message("method.is.overriden.header"); + @NonNls String pattern = "    {1}"; + return GutterIconTooltipHelper.composeText(overridings, start, pattern); + } + + public static void navigateToOverriddenMethod(MouseEvent e, final PsiMethod method) { + if (DumbService.isDumb(method.getProject())) { + DumbService.getInstance(method.getProject()).showDumbModeNotification( + "Navigation to overriding classes is not possible during index update"); + return; + } + + final PsiElementProcessor.CollectElementsWithLimit collectProcessor = + new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + OverridingMethodsSearch.search(method, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + } + }, SEARCHING_FOR_OVERRIDING_METHODS, true, method.getProject(), (JComponent)e.getComponent())) { + return; + } + + PsiMethod[] overridings = collectProcessor.toArray(PsiMethod.EMPTY_ARRAY); + if (overridings.length == 0) return; + boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings); + MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames); + Arrays.sort(overridings, renderer.getComparator()); + final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer); + PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater); + } + public static final String SEARCHING_FOR_OVERRIDDEN_METHODS = "Searching for overridden methods"; public static final MarkerType SUBCLASSED_CLASS = new MarkerType(new NullableFunction() { @Override @@ -154,58 +174,66 @@ public class MarkerType { PsiElement parent = element.getParent(); if (!(parent instanceof PsiClass)) return null; PsiClass aClass = (PsiClass)parent; - PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); - ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); - - if (processor.isOverflow()) { - return aClass.isInterface() - ? DaemonBundle.message("interface.is.implemented.too.many") - : DaemonBundle.message("class.is.subclassed.too.many"); - } - - PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]); - if (subclasses.length == 0) return null; - - Comparator comparator = new PsiClassListCellRenderer().getComparator(); - Arrays.sort(subclasses, comparator); - - String start = aClass.isInterface() - ? DaemonBundle.message("interface.is.implemented.by.header") - : DaemonBundle.message("class.is.subclassed.by.header"); - @NonNls String pattern = "    {0}"; - return GutterIconTooltipHelper.composeText(subclasses, start, pattern); + return getSubclassedClassTooltip(aClass); } }, new LineMarkerNavigator(){ @Override public void browse(MouseEvent e, PsiElement element) { final PsiElement parent = element.getParent(); if (!(parent instanceof PsiClass)) return; - - if (DumbService.isDumb(element.getProject())) { - DumbService.getInstance(element.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); - return; - } - final PsiClass aClass = (PsiClass)parent; - final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); - } - }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { - return; - } - PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY); - if (inheritors.length == 0) return; - final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer(); - final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); - Arrays.sort(inheritors, renderer.getComparator()); - PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), renderer, subclassUpdater); + navigateToSubclassedClass(e, aClass); } }); + public static String getSubclassedClassTooltip(PsiClass aClass) { + PsiElementProcessor.CollectElementsWithLimit processor = new PsiElementProcessor.CollectElementsWithLimit(5, new THashSet()); + ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(processor)); + + if (processor.isOverflow()) { + return aClass.isInterface() + ? DaemonBundle.message("interface.is.implemented.too.many") + : DaemonBundle.message("class.is.subclassed.too.many"); + } + + PsiClass[] subclasses = processor.toArray(new PsiClass[processor.getCollection().size()]); + if (subclasses.length == 0) return null; + + Comparator comparator = new PsiClassListCellRenderer().getComparator(); + Arrays.sort(subclasses, comparator); + + String start = aClass.isInterface() + ? DaemonBundle.message("interface.is.implemented.by.header") + : DaemonBundle.message("class.is.subclassed.by.header"); + @NonNls String pattern = "    {0}"; + return GutterIconTooltipHelper.composeText(subclasses, start, pattern); + } + + public static void navigateToSubclassedClass(MouseEvent e, final PsiClass aClass) { + if (DumbService.isDumb(aClass.getProject())) { + DumbService.getInstance(aClass.getProject()).showDumbModeNotification("Navigation to overriding methods is not possible during index update"); + return; + } + + final PsiElementProcessor.CollectElementsWithLimit collectProcessor = new PsiElementProcessor.CollectElementsWithLimit(2, new THashSet()); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + @Override + public void run() { + ClassInheritorsSearch.search(aClass, true).forEach(new PsiElementProcessorAdapter(collectProcessor)); + } + }, SEARCHING_FOR_OVERRIDDEN_METHODS, true, aClass.getProject(), (JComponent)e.getComponent())) { + return; + } + + PsiClass[] inheritors = collectProcessor.toArray(PsiClass.EMPTY_ARRAY); + if (inheritors.length == 0) return; + final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer(); + final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer); + Arrays.sort(inheritors, renderer.getComparator()); + PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), renderer, subclassUpdater); + } + private final GutterIconNavigationHandler handler; private final Function myTooltip; From 7f07f93ab28f0afa5ffc49de9e6ab95b4a76c0e7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 1 Jun 2012 12:31:49 +0200 Subject: [PATCH 073/239] read ProjectRootManager state in CoreProjectLoader --- .../intellij/core/CoreModuleManagerTest.java | 11 ++++++----- .../com/intellij/core/CoreProjectLoader.java | 17 +++++++++++++++-- .../intellij/core/ProjectModelEnvironment.java | 2 ++ 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/core/CoreModuleManagerTest.java b/platform/platform-tests/testSrc/com/intellij/core/CoreModuleManagerTest.java index 07b3e10b0f49..69950d9b08e4 100644 --- a/platform/platform-tests/testSrc/com/intellij/core/CoreModuleManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/core/CoreModuleManagerTest.java @@ -18,10 +18,8 @@ package com.intellij.core; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.LibraryOrderEntry; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.vfs.StandardFileSystems; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.UsefulTestCase; @@ -33,7 +31,7 @@ import java.io.IOException; * @author yole */ public class CoreModuleManagerTest extends UsefulTestCase { - public void _testLoadingModules() throws IOException, JDOMException { + public void _testLoadingModules() throws IOException, JDOMException, InvalidDataException { CoreEnvironment env = new CoreEnvironment(getTestRootDisposable()); ProjectModelEnvironment.register(env); final String projectPath = PathManagerEx.getTestDataPath("/core/loadingTest"); @@ -43,6 +41,9 @@ public class CoreModuleManagerTest extends UsefulTestCase { final Module[] modules = moduleManager.getModules(); assertEquals(1, modules.length); + ProjectRootManager projectRootManager = ProjectRootManager.getInstance(env.getProject()); + assertEquals("1.6", projectRootManager.getProjectSdkName()); + ModuleRootManager rootManager = ModuleRootManager.getInstance(modules[0]); final ContentEntry[] contentEntries = rootManager.getContentEntries(); assertEquals(1, contentEntries.length); diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java b/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java index 0ca408a943a3..635f9fa27352 100644 --- a/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java +++ b/platform/projectModel-impl/src/com/intellij/core/CoreProjectLoader.java @@ -22,10 +22,13 @@ import com.intellij.openapi.components.impl.stores.DirectoryStorageData; import com.intellij.openapi.components.impl.stores.StorageData; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.impl.DirectoryIndex; import com.intellij.openapi.roots.impl.DirectoryIndexImpl; +import com.intellij.openapi.roots.impl.ProjectRootManagerImpl; import com.intellij.openapi.roots.impl.libraries.LibraryTableBase; import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; +import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.io.fs.FileSystem; @@ -41,7 +44,8 @@ import java.io.IOException; * @author yole */ public class CoreProjectLoader { - public static void loadProject(MockProject project, @NotNull VirtualFile virtualFile) throws IOException, JDOMException { + public static void loadProject(MockProject project, @NotNull VirtualFile virtualFile) + throws IOException, JDOMException, InvalidDataException { if (virtualFile.isDirectory() && virtualFile.findChild(Project.DIRECTORY_STORE_FOLDER) != null) { project.setBaseDir(virtualFile); loadDirectoryProject(project, virtualFile); @@ -52,7 +56,8 @@ public class CoreProjectLoader { } } - private static void loadDirectoryProject(Project project, VirtualFile projectDir) throws IOException, JDOMException { + private static void loadDirectoryProject(Project project, VirtualFile projectDir) throws IOException, JDOMException, + InvalidDataException { VirtualFile dotIdea = projectDir.findChild(Project.DIRECTORY_STORE_FOLDER); VirtualFile modulesXml = dotIdea.findChild("modules.xml"); StorageData storageData = loadStorageFile(project, modulesXml); @@ -63,6 +68,14 @@ public class CoreProjectLoader { final CoreModuleManager moduleManager = (CoreModuleManager)ModuleManager.getInstance(project); moduleManager.loadState(moduleManagerState); + VirtualFile miscXml = dotIdea.findChild("misc.xml"); + storageData = loadStorageFile(project, miscXml); + final Element projectRootManagerState = storageData.getState("ProjectRootManager"); + if (projectRootManagerState == null) { + throw new JDOMException("cannot find ProjectRootManager state in misc.xml"); + } + ((ProjectRootManagerImpl) ProjectRootManager.getInstance(project)).readExternal(projectRootManagerState); + VirtualFile libraries = dotIdea.findChild("libraries"); if (libraries != null) { DirectoryStorageData data = new DirectoryStorageData(); diff --git a/platform/projectModel-impl/src/com/intellij/core/ProjectModelEnvironment.java b/platform/projectModel-impl/src/com/intellij/core/ProjectModelEnvironment.java index 5fd165a41f17..ea05242bea81 100644 --- a/platform/projectModel-impl/src/com/intellij/core/ProjectModelEnvironment.java +++ b/platform/projectModel-impl/src/com/intellij/core/ProjectModelEnvironment.java @@ -27,6 +27,7 @@ import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ProjectExtension; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.roots.impl.*; @@ -54,6 +55,7 @@ public class ProjectModelEnvironment { env.registerProjectComponent(ModuleManager.class, new CoreModuleManager(project, env.getParentDisposable())); env.registerProjectComponent(PathMacroManager.class, new ProjectPathMacroManager(pathMacros, project)); env.registerProjectExtensionPoint(DirectoryIndexExcludePolicy.EP_NAME, DirectoryIndexExcludePolicy.class); + env.registerProjectExtensionPoint(ProjectExtension.EP_NAME, ProjectExtension.class); DirectoryIndex index = new DirectoryIndexImpl(project); env.registerProjectComponent(DirectoryIndex.class, index); env.registerProjectComponent(ProjectRootManager.class, new ProjectRootManagerImpl(project, index)); From 96f1c111ed0318e2c46e9444996e4fe083905910 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Fri, 1 Jun 2012 14:44:33 +0400 Subject: [PATCH 074/239] Handle icon renames and moves --- .../IconsReferencesContributor.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/plugins/devkit/src/references/IconsReferencesContributor.java b/plugins/devkit/src/references/IconsReferencesContributor.java index 6086c6cc5839..1ee44066816e 100644 --- a/plugins/devkit/src/references/IconsReferencesContributor.java +++ b/plugins/devkit/src/references/IconsReferencesContributor.java @@ -36,8 +36,10 @@ import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferen import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.usageView.UsageInfo; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; @@ -120,6 +122,45 @@ public class IconsReferencesContributor extends PsiReferenceContributor implemen return null; } + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + PsiElement element = resolve(); + if (element instanceof PsiFile) { + FileReference lastRef = new FileReferenceSet(element).getLastReference(); + return lastRef.handleElementRename(newElementName); + } + else if (element instanceof PsiField) { + String fqn = ((PsiField)element).getContainingClass().getQualifiedName(); + + if (fqn.startsWith("com.intellij.icons.")) { + XmlAttribute parent = (XmlAttribute)getElement().getParent(); + parent.setValue(fqn.substring("com.intellij.icons.".length()) + "." + newElementName); + return parent.getValueElement(); + } + } + + return super.handleElementRename(newElementName); + } + + @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + if (element instanceof PsiFile) { + FileReference lastRef = new FileReferenceSet(element).getLastReference(); + return lastRef.bindToElement(element); + } + else if (element instanceof PsiField) { + String fqn = ((PsiField)element).getContainingClass().getQualifiedName(); + + if (fqn.startsWith("com.intellij.icons.")) { + XmlAttribute parent = (XmlAttribute)getElement().getParent(); + parent.setValue(fqn.substring("com.intellij.icons.".length()) + "." + ((PsiField)element).getName()); + return parent.getValueElement(); + } + } + + return super.bindToElement(element); + } + @NotNull @Override public Object[] getVariants() { From 2e13dc4c4b991e22c94fb0f9bbc74d98b309d0d8 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Fri, 1 Jun 2012 15:27:41 +0400 Subject: [PATCH 075/239] IDEA-86827 --- .../propertyInspector/UIDesignerToolWindowManager.java | 8 +++++++- .../com/intellij/designer/DesignerToolWindowManager.java | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java index 4f2866fa3ab7..d0fa6234802c 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/UIDesignerToolWindowManager.java @@ -17,6 +17,7 @@ package com.intellij.uiDesigner.propertyInspector; import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; @@ -231,7 +232,12 @@ public class UIDesignerToolWindowManager implements ProjectComponent { } public void fileClosed(FileEditorManager source, VirtualFile file) { - processFileEditorChange(getActiveFormFileEditor()); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + processFileEditorChange(getActiveFormFileEditor()); + } + }); } public void selectionChanged(FileEditorManagerEvent event) { diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerToolWindowManager.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerToolWindowManager.java index c0819ebdf19c..edb2628946f8 100644 --- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerToolWindowManager.java +++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/DesignerToolWindowManager.java @@ -22,6 +22,7 @@ import com.intellij.designer.propertyTable.PropertyTablePanel; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; @@ -77,7 +78,12 @@ public final class DesignerToolWindowManager implements ProjectComponent { @Override public void fileClosed(FileEditorManager source, VirtualFile file) { - bindToDesigner(getActiveDesigner()); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + bindToDesigner(getActiveDesigner()); + } + }); } @Override From fc27628d6619ac143fe2a0015f62358feb8f4e43 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 1 Jun 2012 15:42:12 +0400 Subject: [PATCH 076/239] moving xml-tests to community --- .idea/codeStyleSettings.xml | 101 +- .idea/compiler.xml | 6 +- .idea/inspectionProfiles/idea_default.xml | 3 + .../idea_default_no_spellchecker.xml | 3 + .idea/modules.xml | 1 + community-main.iml | 1 + .../fixtures/CodeInsightFixtureTestCase.java | 8 +- .../codeInsight/SearchingInXmlTest.java | 27 + .../intellij/codeInsight/XmlBuilderTest.java | 257 + .../com/intellij/codeInsight/XmlDtdTest.java | 320 + .../intellij/codeInsight/XmlEventsTest.java | 238 + .../intellij/codeInsight/XmlInsightTest.java | 144 + .../intellij/codeInsight/XmlParsingTest.java | 649 ++ .../codeInsight/XmlPerformanceTest.java | 89 + .../intellij/codeInsight/XmlReparseTest.java | 165 + .../intellij/codeInsight/XmlSchemaTest.java | 757 ++ .../com/intellij/codeInsight/XmlTagTest.java | 960 ++ .../intellij/codeInsight/XmlTagWriteTest.java | 61 + .../com/intellij/codeInsight/XmlTestUtil.java | 22 + .../com/intellij/codeInsight/XmlTextTest.java | 86 + .../XmlWrongClosingTagNameInspectionTest.java | 23 + .../codeInsight/XmlXIncludeTest.groovy | 99 + .../completion/XmlSmartEnterTest.java | 121 + .../moveUpDown/XmlMoverTest.java | 66 + .../psi/formatter/XmlFormatterTestBase.java | 54 + .../psi/formatter/XmlFormatterTestCase.java | 25 + .../HtmlConditionalCommentInjectionTest.java | 28 + .../com/intellij/xml/XmlConstraintsTest.java | 145 + .../com/intellij/xml/XmlNamespacesTest.java | 249 + .../com/intellij/xml/XmlSchemaPrefixTest.java | 47 + .../intellij/xml/XmlSmartCompletionTest.java | 118 + .../xml/actions/GenerateXmlTagTest.java | 84 + .../xml/actions/SplitTagActionTest.java | 26 + .../xml/index/XmlSchemaIndexTest.java | 91 + .../commentInjection/broken_syntax.html | 14 + .../commentInjection/broken_syntax.xhtml | 15 + .../commentInjection/broken_syntax2.html | 14 + .../commentInjection/broken_syntax2.xhtml | 15 + .../testData/commentInjection/complete.html | 13 + .../testData/commentInjection/complete.xhtml | 15 + .../commentInjection/complete_after.html | 13 + .../commentInjection/complete_after.xhtml | 15 + .../testData/commentInjection/injected1.html | 14 + .../testData/commentInjection/injected1.xhtml | 16 + .../testData/commentInjection/injected2.html | 22 + .../formatting1.html | 18 + .../formatting1_after.html | 18 + .../formatting2.html | 36 + .../formatting2_after.html | 36 + .../xhtmlFormatting1.xhtml | 21 + .../xhtmlFormatting1_after.xhtml | 21 + .../xhtmlFormatting2.xhtml | 39 + .../xhtmlFormatting2_after.xhtml | 39 + xml/tests/testData/constraints/test.xml | 3 + xml/tests/testData/constraints/test.xsd | 13 + .../testData/constraints/testCompletion.xml | 4 + xml/tests/testData/constraints/testDtd.xml | 10 + .../testData/constraints/testIncomplete.xml | 3 + xml/tests/testData/generateTag/generate.xml | 8 + .../testData/generateTag/generateDTD.xml | 17 + .../generateTag/generateDTDComplex.xml | 19 + .../generateTag/generateDTDComplex_after.xml | 22 + .../generateTag/generateDTD_after.xml | 20 + .../testData/generateTag/generateEmpty.xml | 8 + .../generateTag/generateEmpty_after.xml | 8 + .../testData/generateTag/generate_after.xml | 13 + xml/tests/testData/generateTag/initParam.xml | 9 + .../testData/generateTag/initParam_after.xml | 12 + xml/tests/testData/generateTag/javaee_5.xsd | 2117 +++++ .../testData/generateTag/spring-beans_3.0.xsd | 1162 +++ xml/tests/testData/generateTag/spring.xml | 8 + .../testData/generateTag/springAfterBean.xml | 11 + .../generateTag/springAfterBean_after.xml | 11 + .../testData/generateTag/springAlias.xml | 8 + .../generateTag/springAlias_after.xml | 8 + .../testData/generateTag/springAtCaret.xml | 9 + .../generateTag/springAtCaret_after.xml | 9 + .../testData/generateTag/spring_after.xml | 8 + .../testData/generateTag/web-app_2_3.dtd | 1063 +++ .../testData/generateTag/web-app_2_5.xsd | 1290 +++ .../generateactions/addColumn/after1.html | 43 + .../generateactions/addColumn/after2.xhtml | 41 + .../generateactions/addColumn/after3.jsp | 74 + .../generateactions/addColumn/after4.jspx | 74 + .../generateactions/addColumn/after5.html | 79 + .../generateactions/addColumn/after6.html | 11 + .../generateactions/addColumn/after7.html | 966 ++ .../generateactions/addColumn/after8.xml | 41 + .../generateactions/addColumn/before1.html | 41 + .../generateactions/addColumn/before2.xhtml | 41 + .../generateactions/addColumn/before3.jsp | 69 + .../generateactions/addColumn/before4.jspx | 69 + .../generateactions/addColumn/before5.html | 69 + .../generateactions/addColumn/before6.html | 6 + .../generateactions/addColumn/before7.html | 866 ++ .../generateactions/addColumn/before8.xml | 41 + xml/tests/testData/index/XMLSchema.xsd | 2468 +++++ xml/tests/testData/index/spring-beans-2.0.xsd | 1076 +++ xml/tests/testData/index/spring-tool-2.0.xsd | 62 + .../deprecatedTag/SwitchToHtml5QuickFix.html | 8 + .../deprecatedTag/SwitchToHtml5QuickFix1.html | 10 + .../deprecatedTag/actions/after0.html | 12 + .../deprecatedTag/actions/after1.html | 12 + .../deprecatedTag/actions/after2.jspx | 11 + .../deprecatedTag/actions/after3.jsp | 33 + .../deprecatedTag/actions/before0.html | 12 + .../deprecatedTag/actions/before1.html | 12 + .../deprecatedTag/actions/before2.jspx | 11 + .../deprecatedTag/actions/before3.jsp | 2 + .../deprecatedTag/html_deptag5.xhtml | 4 + .../deprecatedTag/html_deptag5.xml | 9 + .../formInputWithoutLabel/actions/after1.html | 13 + .../actions/after2.xhtml | 15 + .../formInputWithoutLabel/actions/after3.jsp | 11 + .../formInputWithoutLabel/actions/after4.jspx | 15 + .../formInputWithoutLabel/actions/after5.html | 11 + .../actions/after6.xhtml | 12 + .../formInputWithoutLabel/actions/after7.jsp | 8 + .../actions/before1.html | 11 + .../actions/before2.xhtml | 13 + .../formInputWithoutLabel/actions/before3.jsp | 9 + .../actions/before4.jspx | 13 + .../actions/before5.html | 11 + .../actions/before6.xhtml | 13 + .../formInputWithoutLabel/actions/before7.jsp | 9 + .../formInputWithoutLabel/nowarnings.html | 31 + .../formInputWithoutLabel/nowarnings.xml | 10 + .../inspections/presentationalTag/after0.jspx | 11 + .../presentationalTag/before0.jspx | 11 + .../wrongClosingTagName/after0.xhtml | 10 + .../wrongClosingTagName/after1.xhtml | 10 + .../wrongClosingTagName/after2.xhtml | 10 + .../wrongClosingTagName/after3.xml | 3 + .../wrongClosingTagName/before0.xhtml | 10 + .../wrongClosingTagName/before1.xhtml | 10 + .../wrongClosingTagName/before2.xhtml | 10 + .../wrongClosingTagName/before3.xml | 3 + .../testData/intentions/splitTag/after1.html | 13 + .../testData/intentions/splitTag/after3.html | 13 + .../testData/intentions/splitTag/after4.html | 2 + .../testData/intentions/splitTag/before0.html | 13 + .../testData/intentions/splitTag/before1.html | 11 + .../testData/intentions/splitTag/before2.html | 11 + .../testData/intentions/splitTag/before3.html | 11 + .../testData/intentions/splitTag/before4.html | 2 + xml/tests/testData/mover/1.html | 9 + xml/tests/testData/mover/1_afterDown.html | 9 + xml/tests/testData/mover/1_afterUp.html | 9 + xml/tests/testData/mover/tag.xml | 5 + xml/tests/testData/mover/tag10.xml | 3 + xml/tests/testData/mover/tag11.xml | 6 + xml/tests/testData/mover/tag11_afterDown.xml | 6 + xml/tests/testData/mover/tag11_afterUp.xml | 6 + xml/tests/testData/mover/tag2.xml | 5 + xml/tests/testData/mover/tag2_afterDown.xml | 5 + xml/tests/testData/mover/tag2_afterUp.xml | 5 + xml/tests/testData/mover/tag3.xml | 10 + xml/tests/testData/mover/tag3_afterDown.xml | 10 + xml/tests/testData/mover/tag3_afterUp.xml | 10 + xml/tests/testData/mover/tag4.xml | 7 + xml/tests/testData/mover/tag4_afterUp.xml | 7 + xml/tests/testData/mover/tag5.xml | 11 + xml/tests/testData/mover/tag5_afterUp.xml | 11 + xml/tests/testData/mover/tag6.xml | 11 + xml/tests/testData/mover/tag6_afterDown.xml | 11 + xml/tests/testData/mover/tag6_afterUp.xml | 11 + xml/tests/testData/mover/tag7.xml | 11 + xml/tests/testData/mover/tag7_afterDown.xml | 11 + xml/tests/testData/mover/tag7_afterUp.xml | 11 + xml/tests/testData/mover/tag8.xml | 16 + xml/tests/testData/mover/tag8_afterDown.xml | 16 + xml/tests/testData/mover/tag8_afterUp.xml | 16 + xml/tests/testData/mover/tag9.xml | 15 + xml/tests/testData/mover/tag9_afterDown.xml | 15 + xml/tests/testData/mover/tag9_afterUp.xml | 15 + xml/tests/testData/mover/tag_afterDown.xml | 5 + xml/tests/testData/mover/tag_afterUp.xml | 5 + .../testData/navigateactions/after1.html | 41 + .../testData/navigateactions/after2.xhtml | 41 + xml/tests/testData/navigateactions/after3.jsp | 69 + .../testData/navigateactions/after4.jspx | 69 + .../testData/navigateactions/before1.html | 41 + .../testData/navigateactions/before2.xhtml | 41 + .../testData/navigateactions/before3.jsp | 69 + .../testData/navigateactions/before4.jspx | 69 + .../testData/navigateactions/before8.xml | 41 + .../testData/performance/IndentUnindent.xml | 3361 +++++++ .../testData/performance/IndentUnindent2.xml | 2870 ++++++ xml/tests/testData/psi/events/1.txt | 1 + xml/tests/testData/psi/events/2.txt | 1 + xml/tests/testData/psi/events/3.txt | 1 + xml/tests/testData/psi/events/4.txt | 1 + xml/tests/testData/psi/events/5.txt | 1 + xml/tests/testData/psi/events/BulkUpdate.txt | 1 + .../testData/psi/events/DocumentChange1.txt | 1 + .../testData/psi/events/DocumentChange2.txt | 1 + .../testData/psi/events/DocumentChange3.txt | 1 + xml/tests/testData/psi/events/TagRemove.txt | 1 + .../psi/incrementalReparse41_after.xml | 1594 ++++ .../psi/incrementalReparse41_before.xml | 1594 ++++ .../psi/incrementalReparse42_after.xml | 10 + .../psi/incrementalReparse42_before.xml | 10 + .../psi/incrementalReparse43_after.xml | 100 + .../psi/incrementalReparse43_before.xml | 99 + .../psi/incrementalReparse46_after.xml | 14 + .../psi/incrementalReparse46_before.xml | 14 + .../psi/incrementalReparse47_after.xml | 14 + .../psi/incrementalReparse47_before.xml | 14 + xml/tests/testData/psi/manyErrors.xml | 258 + xml/tests/testData/psi/pallada.xml | 2424 +++++ xml/tests/testData/psi/performance2.xml | 7931 +++++++++++++++++ xml/tests/testData/psi/test1.xml | 145 + xml/tests/testData/psi/testAttlist1.txt | 23 + xml/tests/testData/psi/testAttlist2.txt | 26 + xml/tests/testData/psi/testAttlist3.txt | 21 + xml/tests/testData/psi/testAttlist4.txt | 20 + xml/tests/testData/psi/testAttributes1.txt | 27 + xml/tests/testData/psi/testAttributes2.txt | 30 + xml/tests/testData/psi/testAttributes3.txt | 31 + xml/tests/testData/psi/testAttributes4.txt | 31 + xml/tests/testData/psi/testAttributes5.txt | 37 + xml/tests/testData/psi/testCdata1.txt | 16 + xml/tests/testData/psi/testCdata2.txt | 16 + xml/tests/testData/psi/testCharRef1.txt | 13 + xml/tests/testData/psi/testCharRef2.txt | 13 + xml/tests/testData/psi/testCharRef3.txt | 9 + xml/tests/testData/psi/testCharRef4.txt | 9 + xml/tests/testData/psi/testCharRef5.txt | 17 + xml/tests/testData/psi/testCharacters1.txt | 15 + xml/tests/testData/psi/testComment1.txt | 11 + xml/tests/testData/psi/testComment2.txt | 32 + xml/tests/testData/psi/testComment3.txt | 15 + .../testData/psi/testConditionalSection1.txt | 21 + .../testData/psi/testConditionalSection2.txt | 33 + .../testData/psi/testConditionalSection3.txt | 49 + xml/tests/testData/psi/testContent1.txt | 15 + xml/tests/testData/psi/testDoctype1.txt | 15 + xml/tests/testData/psi/testDoctype2.txt | 17 + xml/tests/testData/psi/testDoctype3.txt | 26 + xml/tests/testData/psi/testDoctype4.txt | 23 + xml/tests/testData/psi/testDoctype5.txt | 37 + xml/tests/testData/psi/testDoctype6.txt | 26 + xml/tests/testData/psi/testDoctype7.txt | 38 + xml/tests/testData/psi/testDtd1.txt | 28 + xml/tests/testData/psi/testEditing1.txt | 16 + xml/tests/testData/psi/testEditing2.txt | 26 + xml/tests/testData/psi/testEditing3.txt | 21 + xml/tests/testData/psi/testEditing4.txt | 26 + xml/tests/testData/psi/testEditing5.txt | 23 + xml/tests/testData/psi/testEditing6.txt | 21 + xml/tests/testData/psi/testEditing7.txt | 23 + xml/tests/testData/psi/testEditing8.txt | 29 + xml/tests/testData/psi/testEditing9.txt | 42 + xml/tests/testData/psi/testElementDecl1.txt | 12 + xml/tests/testData/psi/testElementDecl2.txt | 12 + .../testData/psi/testElementDeclaration.txt | 61 + xml/tests/testData/psi/testElements1.txt | 11 + xml/tests/testData/psi/testElements2.txt | 8 + xml/tests/testData/psi/testElements3.txt | 41 + xml/tests/testData/psi/testElements4.txt | 43 + xml/tests/testData/psi/testElements5.txt | 15 + xml/tests/testData/psi/testElements6.txt | 31 + .../testData/psi/testEmptyCommentParsing.txt | 10 + .../testData/psi/testEmptyElementsInDtd.txt | 69 + xml/tests/testData/psi/testEntityDecl1.txt | 16 + xml/tests/testData/psi/testEntityDecl2.txt | 14 + xml/tests/testData/psi/testEntityDecl3.txt | 16 + xml/tests/testData/psi/testEntityDecl4.txt | 21 + .../testData/psi/testEntityDeclaration.txt | 19 + .../testData/psi/testEntityDeclaration2.txt | 12 + .../psi/testEntityInAttlistDeclaration.txt | 13 + xml/tests/testData/psi/testEntityInAttr.txt | 18 + .../testData/psi/testEntityInContent.txt | 17 + xml/tests/testData/psi/testEntityRef1.txt | 13 + xml/tests/testData/psi/testEntityRef3.txt | 30 + xml/tests/testData/psi/testEntityRef4.txt | 19 + xml/tests/testData/psi/testEntityRef5.txt | 23 + xml/tests/testData/psi/testEntityRef6.txt | 6 + xml/tests/testData/psi/testEntityRef7.txt | 31 + xml/tests/testData/psi/testGtInTagContent.txt | 13 + .../psi/testManualEmptyAttributeParsing.txt | 26 + xml/tests/testData/psi/testManyErrors.txt | 3709 ++++++++ xml/tests/testData/psi/testMultyRoots.txt | 21 + .../psi/testMultyRootsWithErrorsBetween.txt | 25 + xml/tests/testData/psi/testNewParsing1.txt | 11 + xml/tests/testData/psi/testNewParsing10.txt | 29 + xml/tests/testData/psi/testNewParsing11.txt | 36 + xml/tests/testData/psi/testNewParsing12.txt | 26 + xml/tests/testData/psi/testNewParsing13.txt | 34 + xml/tests/testData/psi/testNewParsing14.txt | 27 + xml/tests/testData/psi/testNewParsing15.txt | 47 + xml/tests/testData/psi/testNewParsing16.txt | 24 + xml/tests/testData/psi/testNewParsing17.txt | 334 + xml/tests/testData/psi/testNewParsing18.txt | 1372 +++ xml/tests/testData/psi/testNewParsing19.txt | 65 + xml/tests/testData/psi/testNewParsing2.txt | 13 + xml/tests/testData/psi/testNewParsing20.txt | 26 + xml/tests/testData/psi/testNewParsing3.txt | 14 + xml/tests/testData/psi/testNewParsing4.txt | 21 + xml/tests/testData/psi/testNewParsing5.txt | 19 + xml/tests/testData/psi/testNewParsing6.txt | 40 + xml/tests/testData/psi/testNewParsing7.txt | 37 + xml/tests/testData/psi/testNewParsing8.txt | 16 + xml/tests/testData/psi/testNewParsing9.txt | 19 + xml/tests/testData/psi/testNotation1.txt | 16 + xml/tests/testData/psi/testNotation2.txt | 27 + .../psi/testProcessingInstruction1.txt | 12 + .../psi/testProcessingInstruction2.txt | 17 + .../psi/testProcessingInstruction3.txt | 49 + xml/tests/testData/psi/testPrologInDtd.txt | 40 + xml/tests/testData/psi/testSGMLDtd.txt | 100 + xml/tests/testData/psi/testUnbalanced1.txt | 17 + xml/tests/testData/psi/testUnbalanced2.txt | 23 + xml/tests/testData/psi/testUnbalanced3.txt | 18 + xml/tests/testData/psi/testUnbalanced4.txt | 22 + xml/tests/testData/psi/testUnclosedTag.txt | 12 + xml/tests/testData/psi/testUnclosedTag2.txt | 9 + xml/tests/testData/psi/testUnopenedTag1.txt | 11 + xml/tests/testData/psi/testXmlDecl.txt | 25 + xml/tests/testData/psi/testXmlDecl2.txt | 30 + xml/tests/testData/psi/testXmlDecl3.txt | 33 + xml/tests/testData/psi/testXmlDeclDtd.txt | 52 + xml/tests/testData/psi/xi/include1.xml | 9 + xml/tests/testData/psi/xi/testBasicXi.xml | 5 + xml/tests/testData/psi/xi/testXpointerXi1.xml | 5 + xml/tests/testData/schemaPrefix/rename.xml | 17 + xml/tests/testData/schemaPrefix/rename1.xml | 17 + .../testData/schemaPrefix/rename1_after.xml | 17 + xml/tests/testData/schemaPrefix/rename2.xml | 17 + .../testData/schemaPrefix/rename2_after.xml | 17 + .../schemaPrefix/renameFromClosingTag.xml | 17 + .../renameFromClosingTag_after.xml | 17 + .../testData/schemaPrefix/rename_after.xml | 17 + xml/tests/testData/schemaPrefix/usages.xml | 18 + xml/tests/testData/schemaPrefix/usages1.xml | 18 + .../testData/smartCompletion/Servlet.xml | 10 + xml/tests/testData/smartCompletion/test.xsd | 13 + .../smartCompletion/testCompletion.xml | 3 + .../smartCompletion/testCompletion3.xml | 5 + .../smartCompletion/testCompletionNext.xml | 4 + .../testData/smartCompletion/web-app_2_3.dtd | 1063 +++ .../testData/smartEnter/IDEADEV_29628.xml | 1 + .../smartEnter/IDEADEV_29628_after.xml | 1 + .../testData/smartEnter/IDEADEV_32164.jsp | 1 + .../testData/smartEnter/IDEADEV_32164_2.jsp | 5 + .../smartEnter/IDEADEV_32164_2_after.jsp | 5 + .../smartEnter/IDEADEV_32164_after.jsp | 1 + .../testData/smartEnter/OpenAttribute.xml | 1 + .../smartEnter/OpenAttribute_after.xml | 1 + .../testData/smartEnter/SmartFinish1.xml | 4 + .../smartEnter/SmartFinish1_after.xml | 4 + .../testData/smartEnter/SmartFinish2.xml | 4 + .../smartEnter/SmartFinish2_after.xml | 6 + .../testData/smartEnter/SmartFinish3.xml | 4 + .../smartEnter/SmartFinish3_after.xml | 6 + xml/tests/testData/smartEnter/Tag.jsp | 3 + xml/tests/testData/smartEnter/Tag.xml | 1 + xml/tests/testData/smartEnter/Tag_after.jsp | 3 + xml/tests/testData/smartEnter/Tag_after.xml | 1 + .../testData/smartEnter/WrongAttribute.xml | 1 + .../smartEnter/WrongAttribute_after.xml | 1 + xml/tests/testData/unusedNs/moved.xml | 4 + xml/tests/testData/unusedNs/trg/move-def.xsd | 9 + xml/tests/testData/unusedNs/web-app_2_5.xsd | 1290 +++ xml/tests/testData/unusedNs/wsdd.dtd | 53 + .../testData/unusedNs/wsdd_provider_java.xsd | 1 + xml/tests/xml-tests.iml | 23 + 367 files changed, 49992 insertions(+), 25 deletions(-) create mode 100644 xml/tests/src/com/intellij/codeInsight/SearchingInXmlTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlBuilderTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlDtdTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlEventsTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlInsightTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlParsingTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlPerformanceTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlReparseTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlSchemaTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlTagTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlTestUtil.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlTextTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/XmlXIncludeTest.groovy create mode 100644 xml/tests/src/com/intellij/codeInsight/completion/XmlSmartEnterTest.java create mode 100644 xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java create mode 100644 xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestBase.java create mode 100644 xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java create mode 100644 xml/tests/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjectionTest.java create mode 100644 xml/tests/src/com/intellij/xml/XmlConstraintsTest.java create mode 100644 xml/tests/src/com/intellij/xml/XmlNamespacesTest.java create mode 100644 xml/tests/src/com/intellij/xml/XmlSchemaPrefixTest.java create mode 100644 xml/tests/src/com/intellij/xml/XmlSmartCompletionTest.java create mode 100644 xml/tests/src/com/intellij/xml/actions/GenerateXmlTagTest.java create mode 100644 xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java create mode 100644 xml/tests/src/com/intellij/xml/index/XmlSchemaIndexTest.java create mode 100644 xml/tests/testData/commentInjection/broken_syntax.html create mode 100644 xml/tests/testData/commentInjection/broken_syntax.xhtml create mode 100644 xml/tests/testData/commentInjection/broken_syntax2.html create mode 100644 xml/tests/testData/commentInjection/broken_syntax2.xhtml create mode 100644 xml/tests/testData/commentInjection/complete.html create mode 100644 xml/tests/testData/commentInjection/complete.xhtml create mode 100644 xml/tests/testData/commentInjection/complete_after.html create mode 100644 xml/tests/testData/commentInjection/complete_after.xhtml create mode 100644 xml/tests/testData/commentInjection/injected1.html create mode 100644 xml/tests/testData/commentInjection/injected1.xhtml create mode 100644 xml/tests/testData/commentInjection/injected2.html create mode 100644 xml/tests/testData/commentInjectionFormatting/formatting1.html create mode 100644 xml/tests/testData/commentInjectionFormatting/formatting1_after.html create mode 100644 xml/tests/testData/commentInjectionFormatting/formatting2.html create mode 100644 xml/tests/testData/commentInjectionFormatting/formatting2_after.html create mode 100644 xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1.xhtml create mode 100644 xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1_after.xhtml create mode 100644 xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2.xhtml create mode 100644 xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2_after.xhtml create mode 100644 xml/tests/testData/constraints/test.xml create mode 100644 xml/tests/testData/constraints/test.xsd create mode 100644 xml/tests/testData/constraints/testCompletion.xml create mode 100644 xml/tests/testData/constraints/testDtd.xml create mode 100644 xml/tests/testData/constraints/testIncomplete.xml create mode 100644 xml/tests/testData/generateTag/generate.xml create mode 100644 xml/tests/testData/generateTag/generateDTD.xml create mode 100644 xml/tests/testData/generateTag/generateDTDComplex.xml create mode 100644 xml/tests/testData/generateTag/generateDTDComplex_after.xml create mode 100644 xml/tests/testData/generateTag/generateDTD_after.xml create mode 100644 xml/tests/testData/generateTag/generateEmpty.xml create mode 100644 xml/tests/testData/generateTag/generateEmpty_after.xml create mode 100644 xml/tests/testData/generateTag/generate_after.xml create mode 100644 xml/tests/testData/generateTag/initParam.xml create mode 100644 xml/tests/testData/generateTag/initParam_after.xml create mode 100644 xml/tests/testData/generateTag/javaee_5.xsd create mode 100644 xml/tests/testData/generateTag/spring-beans_3.0.xsd create mode 100644 xml/tests/testData/generateTag/spring.xml create mode 100644 xml/tests/testData/generateTag/springAfterBean.xml create mode 100644 xml/tests/testData/generateTag/springAfterBean_after.xml create mode 100644 xml/tests/testData/generateTag/springAlias.xml create mode 100644 xml/tests/testData/generateTag/springAlias_after.xml create mode 100644 xml/tests/testData/generateTag/springAtCaret.xml create mode 100644 xml/tests/testData/generateTag/springAtCaret_after.xml create mode 100644 xml/tests/testData/generateTag/spring_after.xml create mode 100644 xml/tests/testData/generateTag/web-app_2_3.dtd create mode 100644 xml/tests/testData/generateTag/web-app_2_5.xsd create mode 100644 xml/tests/testData/generateactions/addColumn/after1.html create mode 100644 xml/tests/testData/generateactions/addColumn/after2.xhtml create mode 100644 xml/tests/testData/generateactions/addColumn/after3.jsp create mode 100644 xml/tests/testData/generateactions/addColumn/after4.jspx create mode 100644 xml/tests/testData/generateactions/addColumn/after5.html create mode 100644 xml/tests/testData/generateactions/addColumn/after6.html create mode 100644 xml/tests/testData/generateactions/addColumn/after7.html create mode 100644 xml/tests/testData/generateactions/addColumn/after8.xml create mode 100644 xml/tests/testData/generateactions/addColumn/before1.html create mode 100644 xml/tests/testData/generateactions/addColumn/before2.xhtml create mode 100644 xml/tests/testData/generateactions/addColumn/before3.jsp create mode 100644 xml/tests/testData/generateactions/addColumn/before4.jspx create mode 100644 xml/tests/testData/generateactions/addColumn/before5.html create mode 100644 xml/tests/testData/generateactions/addColumn/before6.html create mode 100644 xml/tests/testData/generateactions/addColumn/before7.html create mode 100644 xml/tests/testData/generateactions/addColumn/before8.xml create mode 100644 xml/tests/testData/index/XMLSchema.xsd create mode 100644 xml/tests/testData/index/spring-beans-2.0.xsd create mode 100644 xml/tests/testData/index/spring-tool-2.0.xsd create mode 100644 xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix1.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/after0.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/after1.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/after2.jspx create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/after3.jsp create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/before0.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/before1.html create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/before2.jspx create mode 100644 xml/tests/testData/inspections/deprecatedTag/actions/before3.jsp create mode 100644 xml/tests/testData/inspections/deprecatedTag/html_deptag5.xhtml create mode 100644 xml/tests/testData/inspections/deprecatedTag/html_deptag5.xml create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after1.html create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after2.xhtml create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after3.jsp create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after4.jspx create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after5.html create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after6.xhtml create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/after7.jsp create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before1.html create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before2.xhtml create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before3.jsp create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before4.jspx create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before5.html create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before6.xhtml create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/actions/before7.jsp create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/nowarnings.html create mode 100644 xml/tests/testData/inspections/formInputWithoutLabel/nowarnings.xml create mode 100644 xml/tests/testData/inspections/presentationalTag/after0.jspx create mode 100644 xml/tests/testData/inspections/presentationalTag/before0.jspx create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/after0.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/after1.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/after2.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/after3.xml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/before0.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/before1.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/before2.xhtml create mode 100644 xml/tests/testData/inspections/wrongClosingTagName/before3.xml create mode 100644 xml/tests/testData/intentions/splitTag/after1.html create mode 100644 xml/tests/testData/intentions/splitTag/after3.html create mode 100644 xml/tests/testData/intentions/splitTag/after4.html create mode 100644 xml/tests/testData/intentions/splitTag/before0.html create mode 100644 xml/tests/testData/intentions/splitTag/before1.html create mode 100644 xml/tests/testData/intentions/splitTag/before2.html create mode 100644 xml/tests/testData/intentions/splitTag/before3.html create mode 100644 xml/tests/testData/intentions/splitTag/before4.html create mode 100644 xml/tests/testData/mover/1.html create mode 100644 xml/tests/testData/mover/1_afterDown.html create mode 100644 xml/tests/testData/mover/1_afterUp.html create mode 100644 xml/tests/testData/mover/tag.xml create mode 100644 xml/tests/testData/mover/tag10.xml create mode 100644 xml/tests/testData/mover/tag11.xml create mode 100644 xml/tests/testData/mover/tag11_afterDown.xml create mode 100644 xml/tests/testData/mover/tag11_afterUp.xml create mode 100644 xml/tests/testData/mover/tag2.xml create mode 100644 xml/tests/testData/mover/tag2_afterDown.xml create mode 100644 xml/tests/testData/mover/tag2_afterUp.xml create mode 100644 xml/tests/testData/mover/tag3.xml create mode 100644 xml/tests/testData/mover/tag3_afterDown.xml create mode 100644 xml/tests/testData/mover/tag3_afterUp.xml create mode 100644 xml/tests/testData/mover/tag4.xml create mode 100644 xml/tests/testData/mover/tag4_afterUp.xml create mode 100644 xml/tests/testData/mover/tag5.xml create mode 100644 xml/tests/testData/mover/tag5_afterUp.xml create mode 100644 xml/tests/testData/mover/tag6.xml create mode 100644 xml/tests/testData/mover/tag6_afterDown.xml create mode 100644 xml/tests/testData/mover/tag6_afterUp.xml create mode 100644 xml/tests/testData/mover/tag7.xml create mode 100644 xml/tests/testData/mover/tag7_afterDown.xml create mode 100644 xml/tests/testData/mover/tag7_afterUp.xml create mode 100644 xml/tests/testData/mover/tag8.xml create mode 100644 xml/tests/testData/mover/tag8_afterDown.xml create mode 100644 xml/tests/testData/mover/tag8_afterUp.xml create mode 100644 xml/tests/testData/mover/tag9.xml create mode 100644 xml/tests/testData/mover/tag9_afterDown.xml create mode 100644 xml/tests/testData/mover/tag9_afterUp.xml create mode 100644 xml/tests/testData/mover/tag_afterDown.xml create mode 100644 xml/tests/testData/mover/tag_afterUp.xml create mode 100644 xml/tests/testData/navigateactions/after1.html create mode 100644 xml/tests/testData/navigateactions/after2.xhtml create mode 100644 xml/tests/testData/navigateactions/after3.jsp create mode 100644 xml/tests/testData/navigateactions/after4.jspx create mode 100644 xml/tests/testData/navigateactions/before1.html create mode 100644 xml/tests/testData/navigateactions/before2.xhtml create mode 100644 xml/tests/testData/navigateactions/before3.jsp create mode 100644 xml/tests/testData/navigateactions/before4.jspx create mode 100644 xml/tests/testData/navigateactions/before8.xml create mode 100644 xml/tests/testData/performance/IndentUnindent.xml create mode 100644 xml/tests/testData/performance/IndentUnindent2.xml create mode 100644 xml/tests/testData/psi/events/1.txt create mode 100644 xml/tests/testData/psi/events/2.txt create mode 100644 xml/tests/testData/psi/events/3.txt create mode 100644 xml/tests/testData/psi/events/4.txt create mode 100644 xml/tests/testData/psi/events/5.txt create mode 100644 xml/tests/testData/psi/events/BulkUpdate.txt create mode 100644 xml/tests/testData/psi/events/DocumentChange1.txt create mode 100644 xml/tests/testData/psi/events/DocumentChange2.txt create mode 100644 xml/tests/testData/psi/events/DocumentChange3.txt create mode 100644 xml/tests/testData/psi/events/TagRemove.txt create mode 100644 xml/tests/testData/psi/incrementalReparse41_after.xml create mode 100644 xml/tests/testData/psi/incrementalReparse41_before.xml create mode 100644 xml/tests/testData/psi/incrementalReparse42_after.xml create mode 100644 xml/tests/testData/psi/incrementalReparse42_before.xml create mode 100644 xml/tests/testData/psi/incrementalReparse43_after.xml create mode 100644 xml/tests/testData/psi/incrementalReparse43_before.xml create mode 100644 xml/tests/testData/psi/incrementalReparse46_after.xml create mode 100644 xml/tests/testData/psi/incrementalReparse46_before.xml create mode 100644 xml/tests/testData/psi/incrementalReparse47_after.xml create mode 100644 xml/tests/testData/psi/incrementalReparse47_before.xml create mode 100644 xml/tests/testData/psi/manyErrors.xml create mode 100644 xml/tests/testData/psi/pallada.xml create mode 100644 xml/tests/testData/psi/performance2.xml create mode 100644 xml/tests/testData/psi/test1.xml create mode 100644 xml/tests/testData/psi/testAttlist1.txt create mode 100644 xml/tests/testData/psi/testAttlist2.txt create mode 100644 xml/tests/testData/psi/testAttlist3.txt create mode 100644 xml/tests/testData/psi/testAttlist4.txt create mode 100644 xml/tests/testData/psi/testAttributes1.txt create mode 100644 xml/tests/testData/psi/testAttributes2.txt create mode 100644 xml/tests/testData/psi/testAttributes3.txt create mode 100644 xml/tests/testData/psi/testAttributes4.txt create mode 100644 xml/tests/testData/psi/testAttributes5.txt create mode 100644 xml/tests/testData/psi/testCdata1.txt create mode 100644 xml/tests/testData/psi/testCdata2.txt create mode 100644 xml/tests/testData/psi/testCharRef1.txt create mode 100644 xml/tests/testData/psi/testCharRef2.txt create mode 100644 xml/tests/testData/psi/testCharRef3.txt create mode 100644 xml/tests/testData/psi/testCharRef4.txt create mode 100644 xml/tests/testData/psi/testCharRef5.txt create mode 100644 xml/tests/testData/psi/testCharacters1.txt create mode 100644 xml/tests/testData/psi/testComment1.txt create mode 100644 xml/tests/testData/psi/testComment2.txt create mode 100644 xml/tests/testData/psi/testComment3.txt create mode 100644 xml/tests/testData/psi/testConditionalSection1.txt create mode 100644 xml/tests/testData/psi/testConditionalSection2.txt create mode 100644 xml/tests/testData/psi/testConditionalSection3.txt create mode 100644 xml/tests/testData/psi/testContent1.txt create mode 100644 xml/tests/testData/psi/testDoctype1.txt create mode 100644 xml/tests/testData/psi/testDoctype2.txt create mode 100644 xml/tests/testData/psi/testDoctype3.txt create mode 100644 xml/tests/testData/psi/testDoctype4.txt create mode 100644 xml/tests/testData/psi/testDoctype5.txt create mode 100644 xml/tests/testData/psi/testDoctype6.txt create mode 100644 xml/tests/testData/psi/testDoctype7.txt create mode 100644 xml/tests/testData/psi/testDtd1.txt create mode 100644 xml/tests/testData/psi/testEditing1.txt create mode 100644 xml/tests/testData/psi/testEditing2.txt create mode 100644 xml/tests/testData/psi/testEditing3.txt create mode 100644 xml/tests/testData/psi/testEditing4.txt create mode 100644 xml/tests/testData/psi/testEditing5.txt create mode 100644 xml/tests/testData/psi/testEditing6.txt create mode 100644 xml/tests/testData/psi/testEditing7.txt create mode 100644 xml/tests/testData/psi/testEditing8.txt create mode 100644 xml/tests/testData/psi/testEditing9.txt create mode 100644 xml/tests/testData/psi/testElementDecl1.txt create mode 100644 xml/tests/testData/psi/testElementDecl2.txt create mode 100644 xml/tests/testData/psi/testElementDeclaration.txt create mode 100644 xml/tests/testData/psi/testElements1.txt create mode 100644 xml/tests/testData/psi/testElements2.txt create mode 100644 xml/tests/testData/psi/testElements3.txt create mode 100644 xml/tests/testData/psi/testElements4.txt create mode 100644 xml/tests/testData/psi/testElements5.txt create mode 100644 xml/tests/testData/psi/testElements6.txt create mode 100644 xml/tests/testData/psi/testEmptyCommentParsing.txt create mode 100644 xml/tests/testData/psi/testEmptyElementsInDtd.txt create mode 100644 xml/tests/testData/psi/testEntityDecl1.txt create mode 100644 xml/tests/testData/psi/testEntityDecl2.txt create mode 100644 xml/tests/testData/psi/testEntityDecl3.txt create mode 100644 xml/tests/testData/psi/testEntityDecl4.txt create mode 100644 xml/tests/testData/psi/testEntityDeclaration.txt create mode 100644 xml/tests/testData/psi/testEntityDeclaration2.txt create mode 100644 xml/tests/testData/psi/testEntityInAttlistDeclaration.txt create mode 100644 xml/tests/testData/psi/testEntityInAttr.txt create mode 100644 xml/tests/testData/psi/testEntityInContent.txt create mode 100644 xml/tests/testData/psi/testEntityRef1.txt create mode 100644 xml/tests/testData/psi/testEntityRef3.txt create mode 100644 xml/tests/testData/psi/testEntityRef4.txt create mode 100644 xml/tests/testData/psi/testEntityRef5.txt create mode 100644 xml/tests/testData/psi/testEntityRef6.txt create mode 100644 xml/tests/testData/psi/testEntityRef7.txt create mode 100644 xml/tests/testData/psi/testGtInTagContent.txt create mode 100644 xml/tests/testData/psi/testManualEmptyAttributeParsing.txt create mode 100644 xml/tests/testData/psi/testManyErrors.txt create mode 100644 xml/tests/testData/psi/testMultyRoots.txt create mode 100644 xml/tests/testData/psi/testMultyRootsWithErrorsBetween.txt create mode 100644 xml/tests/testData/psi/testNewParsing1.txt create mode 100644 xml/tests/testData/psi/testNewParsing10.txt create mode 100644 xml/tests/testData/psi/testNewParsing11.txt create mode 100644 xml/tests/testData/psi/testNewParsing12.txt create mode 100644 xml/tests/testData/psi/testNewParsing13.txt create mode 100644 xml/tests/testData/psi/testNewParsing14.txt create mode 100644 xml/tests/testData/psi/testNewParsing15.txt create mode 100644 xml/tests/testData/psi/testNewParsing16.txt create mode 100644 xml/tests/testData/psi/testNewParsing17.txt create mode 100644 xml/tests/testData/psi/testNewParsing18.txt create mode 100644 xml/tests/testData/psi/testNewParsing19.txt create mode 100644 xml/tests/testData/psi/testNewParsing2.txt create mode 100644 xml/tests/testData/psi/testNewParsing20.txt create mode 100644 xml/tests/testData/psi/testNewParsing3.txt create mode 100644 xml/tests/testData/psi/testNewParsing4.txt create mode 100644 xml/tests/testData/psi/testNewParsing5.txt create mode 100644 xml/tests/testData/psi/testNewParsing6.txt create mode 100644 xml/tests/testData/psi/testNewParsing7.txt create mode 100644 xml/tests/testData/psi/testNewParsing8.txt create mode 100644 xml/tests/testData/psi/testNewParsing9.txt create mode 100644 xml/tests/testData/psi/testNotation1.txt create mode 100644 xml/tests/testData/psi/testNotation2.txt create mode 100644 xml/tests/testData/psi/testProcessingInstruction1.txt create mode 100644 xml/tests/testData/psi/testProcessingInstruction2.txt create mode 100644 xml/tests/testData/psi/testProcessingInstruction3.txt create mode 100644 xml/tests/testData/psi/testPrologInDtd.txt create mode 100644 xml/tests/testData/psi/testSGMLDtd.txt create mode 100644 xml/tests/testData/psi/testUnbalanced1.txt create mode 100644 xml/tests/testData/psi/testUnbalanced2.txt create mode 100644 xml/tests/testData/psi/testUnbalanced3.txt create mode 100644 xml/tests/testData/psi/testUnbalanced4.txt create mode 100644 xml/tests/testData/psi/testUnclosedTag.txt create mode 100644 xml/tests/testData/psi/testUnclosedTag2.txt create mode 100644 xml/tests/testData/psi/testUnopenedTag1.txt create mode 100644 xml/tests/testData/psi/testXmlDecl.txt create mode 100644 xml/tests/testData/psi/testXmlDecl2.txt create mode 100644 xml/tests/testData/psi/testXmlDecl3.txt create mode 100644 xml/tests/testData/psi/testXmlDeclDtd.txt create mode 100644 xml/tests/testData/psi/xi/include1.xml create mode 100644 xml/tests/testData/psi/xi/testBasicXi.xml create mode 100644 xml/tests/testData/psi/xi/testXpointerXi1.xml create mode 100644 xml/tests/testData/schemaPrefix/rename.xml create mode 100644 xml/tests/testData/schemaPrefix/rename1.xml create mode 100644 xml/tests/testData/schemaPrefix/rename1_after.xml create mode 100644 xml/tests/testData/schemaPrefix/rename2.xml create mode 100644 xml/tests/testData/schemaPrefix/rename2_after.xml create mode 100644 xml/tests/testData/schemaPrefix/renameFromClosingTag.xml create mode 100644 xml/tests/testData/schemaPrefix/renameFromClosingTag_after.xml create mode 100644 xml/tests/testData/schemaPrefix/rename_after.xml create mode 100644 xml/tests/testData/schemaPrefix/usages.xml create mode 100644 xml/tests/testData/schemaPrefix/usages1.xml create mode 100644 xml/tests/testData/smartCompletion/Servlet.xml create mode 100644 xml/tests/testData/smartCompletion/test.xsd create mode 100644 xml/tests/testData/smartCompletion/testCompletion.xml create mode 100644 xml/tests/testData/smartCompletion/testCompletion3.xml create mode 100644 xml/tests/testData/smartCompletion/testCompletionNext.xml create mode 100644 xml/tests/testData/smartCompletion/web-app_2_3.dtd create mode 100644 xml/tests/testData/smartEnter/IDEADEV_29628.xml create mode 100644 xml/tests/testData/smartEnter/IDEADEV_29628_after.xml create mode 100644 xml/tests/testData/smartEnter/IDEADEV_32164.jsp create mode 100644 xml/tests/testData/smartEnter/IDEADEV_32164_2.jsp create mode 100644 xml/tests/testData/smartEnter/IDEADEV_32164_2_after.jsp create mode 100644 xml/tests/testData/smartEnter/IDEADEV_32164_after.jsp create mode 100644 xml/tests/testData/smartEnter/OpenAttribute.xml create mode 100644 xml/tests/testData/smartEnter/OpenAttribute_after.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish1.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish1_after.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish2.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish2_after.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish3.xml create mode 100644 xml/tests/testData/smartEnter/SmartFinish3_after.xml create mode 100644 xml/tests/testData/smartEnter/Tag.jsp create mode 100644 xml/tests/testData/smartEnter/Tag.xml create mode 100644 xml/tests/testData/smartEnter/Tag_after.jsp create mode 100644 xml/tests/testData/smartEnter/Tag_after.xml create mode 100644 xml/tests/testData/smartEnter/WrongAttribute.xml create mode 100644 xml/tests/testData/smartEnter/WrongAttribute_after.xml create mode 100644 xml/tests/testData/unusedNs/moved.xml create mode 100644 xml/tests/testData/unusedNs/trg/move-def.xsd create mode 100644 xml/tests/testData/unusedNs/web-app_2_5.xsd create mode 100644 xml/tests/testData/unusedNs/wsdd.dtd create mode 100644 xml/tests/testData/unusedNs/wsdd_provider_java.xsd create mode 100644 xml/tests/xml-tests.iml diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index b99a172034b3..af2a19460731 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -90,37 +90,62 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + "); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagFromText.setAttribute("a", "b"); + } + }); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void test2() throws Exception{ + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("aaa"); + final XmlTag otherTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final XmlText xmlText = tagFromText.getValue().getTextElements()[0]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlText.insertAtOffset(otherTag, 2); + } + }); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void test3() throws Exception{ + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("aaa"); + final XmlText xmlText = tagFromText.getValue().getTextElements()[0]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlText.insertText("bb", 2); + } + }); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void test4() throws Exception{ + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("a "); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagFromText.addAfter(tagFromText.getValue().getTextElements()[0], tagFromText.getValue().getTextElements()[0]); + } + }); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void test5() throws Exception{ + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("aaa"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagFromText.delete(); + } + }); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void testBulkUpdate() throws Exception{ + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final PsiFile file = createFile("a.xml", ""); + new WriteCommandAction(getProject()) { + @Override + protected void run(Result result) throws Throwable { + final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file); + ((DocumentEx)document).setInBulkUpdate(true); + document.insertString(0, " "); + commitDocument(document); + ((DocumentEx)document).setInBulkUpdate(false); + } + }.execute(); + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + public void testDocumentChange1() throws Exception{ + final String rootTagText = ""; + final String stringToInsert = "b=\"c\""; + final int positionToInsert = 2; + + checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert); + } + + public void testDocumentChange2() throws Exception{ + final String rootTagText = ""; + final String stringToInsert = "b=\"c\""; + final int positionToInsert = 3; + + checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert); + } + + + public void testDocumentChange3() throws Exception{ + final String rootTagText = ""; + final String stringToInsert = "b=\"c\""; + final int positionToInsert = 6; + + checkEventsByDocumentChange(rootTagText, positionToInsert, stringToInsert); + } + + public void testAttributeValueReplace() throws Exception { + final String text = ""; + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(text); + final XmlAttribute attribute = tag.getAttribute("name", null); + assert attribute != null; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + attribute.setValue("new"); + } + }); + + + assertEquals(attribute.getValue(), "new"); + assertEquals("(Attribute \"name\" for tag \"target\" set to \"\"new\"\")\n", listener.getEventString()); + } + + private void checkEventsByDocumentChange(final String rootTagText, final int positionToInsert, final String stringToInsert) + throws Exception { + final PomModel model = PomManager.getModel(getProject()); + final Listener listener = new Listener(model.getModelAspect(XmlAspect.class)); + model.addModelListener(listener); + final XmlTag tagFromText = ((XmlFile)createFile("file.xml", rootTagText)).getDocument().getRootTag(); + final PsiFileImpl containingFile = (PsiFileImpl)tagFromText.getContainingFile(); + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject()); + final Document document = documentManager.getDocument(containingFile); + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + document.insertString(positionToInsert, stringToInsert); + documentManager.commitDocument(document); + } + }); + } + }, "", null); + + assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString()); + } + + private static class Listener implements PomModelListener{ + private final XmlAspect myAspect; + private final StringBuffer myBuffer = new StringBuffer(); + + public Listener(XmlAspect modelAspect) { + myAspect = modelAspect; + } + + @Override + public void modelChanged(PomModelEvent event) { + final PomChangeSet changeSet = event.getChangeSet(myAspect); + if(changeSet == null) return; + myBuffer.append(changeSet); + myBuffer.append("\n"); + } + + @Override + public boolean isAspectChangeInteresting(PomModelAspect aspect) { + return aspect == myAspect; + } + + String getEventString(){ + return myBuffer.toString(); + } + } + + private static void assertFileTextEquals(String targetDataName, String treeText) throws Exception { + String fullName = PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/')+ "/xml/tests/testData/psi/events" + File.separatorChar + targetDataName; + try{ + String expectedText = loadFile(fullName); + assertEquals(expectedText.trim(), treeText.trim()); + } + catch(FileNotFoundException e){ + //FileUtil.writeToFile(new File(fullName), StringUtil.convertLineSeparators(treeText).getBytes("UTF-8")); + fail("No output file found. Created file "+fullName); + } + } + + + protected static String loadFile(String fullName) throws Exception { + String text = FileUtil.loadFile(new File(fullName)).trim(); + text = StringUtil.convertLineSeparators(text); + return text; + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlInsightTest.java b/xml/tests/src/com/intellij/codeInsight/XmlInsightTest.java new file mode 100644 index 000000000000..cfc5426d279e --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlInsightTest.java @@ -0,0 +1,144 @@ +package com.intellij.codeInsight; + +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.testFramework.PsiTestCase; +import com.intellij.xml.XmlAttributeDescriptor; +import com.intellij.xml.XmlElementDescriptor; +import com.intellij.xml.XmlNSDescriptor; + +/** + * @author Mike + */ +public class XmlInsightTest extends PsiTestCase { + public void testDocumentDescriptor1() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlElementDescriptor element = descriptor.getElementDescriptor(file.getDocument().getRootTag()); + assertNotNull(element); + assertEquals("root", element.getName()); + + element = descriptor.getElementDescriptor(file.getDocument().getRootTag().getSubTags()[0]); + assertNotNull(element); + assertEquals("a", element.getName()); + + element = descriptor.getElementDescriptor(file.getDocument().getRootTag().getSubTags()[1]); + assertNotNull(element); + assertEquals("b", element.getName()); + + element = descriptor.getElementDescriptor(file.getDocument().getRootTag().getSubTags()[2]); + assertNotNull(element); + assertEquals("a", element.getName()); + } + + public void testElementDescriptor1() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + + XmlElementDescriptor[] elements = element.getElementsDescriptors(rootTag); + + assertEquals(2, elements.length); + assertEquals("a", elements[0].getName()); + assertEquals("b", elements[1].getName()); + } + + public void testElementDescriptor2() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + element = element.getElementsDescriptors(rootTag)[0]; + + XmlElementDescriptor[] elements = element.getElementsDescriptors(rootTag.getSubTags()[0]); + + assertEquals(2, elements.length); + assertEquals("b", elements[0].getName()); + assertEquals("c", elements[1].getName()); + } + + public void testElementDescriptor3() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + element = element.getElementsDescriptors(rootTag)[0]; + + XmlElementDescriptor[] elements = element.getElementsDescriptors(rootTag.getSubTags()[0]); + + assertEquals(2, elements.length); + assertEquals("b", elements[0].getName()); + //assertTrue(elements[0].getContentType() == XmlElementDescriptor.CONTENT_TYPE_EMPTY); + + assertEquals("c", elements[1].getName()); + //assertTrue(elements[1].getContentType() == XmlElementDescriptor.CONTENT_TYPE_CHILDREN); + } + + public void testElementDescriptor4() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + element = element.getElementsDescriptors(rootTag)[0]; + + XmlAttributeDescriptor[] attributes = element.getAttributesDescriptors(rootTag); + + assertEquals(2, attributes.length); + assertEquals("attr1", attributes[0].getName()); + assertEquals("attr2", attributes[1].getName()); + } + + public void testAttributeDescriptor1() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + element = element.getElementsDescriptors(rootTag)[0]; + + XmlAttributeDescriptor[] attributes = element.getAttributesDescriptors(rootTag); + + assertEquals("attr1", attributes[0].getName()); + assertTrue(attributes[0].isRequired()); + + assertEquals("attr2", attributes[1].getName()); + assertTrue(!attributes[1].isRequired()); + } + + public void testAttributeDescriptor2() throws Exception { + XmlFile file = createFile(""); + XmlNSDescriptor descriptor = createDescriptor(file); + + XmlTag rootTag = file.getDocument().getRootTag(); + XmlElementDescriptor element = descriptor.getElementDescriptor(rootTag); + element = element.getElementsDescriptors(rootTag)[0]; + + XmlAttributeDescriptor[] attributes = element.getAttributesDescriptors(rootTag); + + assertEquals("c", attributes[0].getName()); + assertTrue(attributes[0].isRequired()); + + assertEquals("a", attributes[1].getName()); + assertTrue(attributes[1].isRequired()); + } + + private XmlFile createFile(String text) throws Exception { + return (XmlFile)createDummyFile("test.xml", text); + } + + private XmlNSDescriptor createDescriptor(XmlFile file) throws Exception{ + return file.getDocument().getRootTagNSDescriptor(); + } + + private XmlTag tag(String tagName) throws Exception { + XmlFile file = (XmlFile)PsiFileFactory.getInstance(myPsiManager.getProject()).createFileFromText("tag.xml", "<" + tagName + "/>"); + return file.getDocument().getRootTag(); + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlParsingTest.java b/xml/tests/src/com/intellij/codeInsight/XmlParsingTest.java new file mode 100644 index 000000000000..b3fe52305eec --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlParsingTest.java @@ -0,0 +1,649 @@ +package com.intellij.codeInsight; + +import com.intellij.lang.ASTFactory; +import com.intellij.lang.ASTNode; +import com.intellij.lang.LanguageASTFactory; +import com.intellij.lang.LanguageParserDefinitions; +import com.intellij.lang.dtd.DTDLanguage; +import com.intellij.lang.dtd.DTDParserDefinition; +import com.intellij.lang.xml.XMLLanguage; +import com.intellij.lang.xml.XMLParserDefinition; +import com.intellij.lang.xml.XmlASTFactory; +import com.intellij.lexer.FilterLexer; +import com.intellij.lexer.Lexer; +import com.intellij.lexer.XmlLexer; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.source.CharTableImpl; +import com.intellij.psi.impl.source.parsing.xml.OldXmlParser; +import com.intellij.psi.impl.source.tree.CompositeElement; +import com.intellij.psi.impl.source.tree.LeafElement; +import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.xml.*; +import com.intellij.testFramework.ParsingTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; +import org.jetbrains.annotations.NonNls; + +import java.io.File; + +/** + * @author Mike, ik + */ +public class XmlParsingTest extends ParsingTestCase { + public XmlParsingTest() { + super("psi", "???"); + myLanguage = XMLLanguage.INSTANCE; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + addExplicitExtension(LanguageParserDefinitions.INSTANCE, XMLLanguage.INSTANCE, new XMLParserDefinition()); + addExplicitExtension(LanguageParserDefinitions.INSTANCE, DTDLanguage.INSTANCE, new DTDParserDefinition()); + addExplicitExtension(LanguageASTFactory.INSTANCE, XMLLanguage.INSTANCE, new XmlASTFactory()); + addExplicitExtension(LanguageASTFactory.INSTANCE, DTDLanguage.INSTANCE, new XmlASTFactory()); + registerExtensionPoint(new ExtensionPointName("com.intellij.xml.startTagEndToken"), + XmlChildRole.StartTagEndTokenProvider.class); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/"; + } + + private void doTestXml(@NonNls String text) throws Exception { + myLanguage = XMLLanguage.INSTANCE; + doTest(text, "test.xml"); + } + private void doTestDtd(@NonNls String text) throws Exception { + myLanguage = DTDLanguage.INSTANCE; + doTest(text, "test.dtd"); + } + private void doTest(@NonNls String text, @NonNls String fileName) throws Exception { + PsiFile file = createFile(fileName, text); + checkResult("test" +getTestName(false), file); + } + + public void testNewParsing1() throws Exception { + doTestXml(""); + } + + public void testEmptyCommentParsing() throws Exception { + doTestXml(""); + } + + public void testNewParsing2() throws Exception { + doTestXml(" "); + } + + public void testNewParsing3() throws Exception { + doTestXml(""); + } + + public void testNewParsing4() throws Exception { + doTestXml(" "); + } + + public void testNewParsing5() throws Exception { + doTestXml(" "); + } + + public void testNewParsing6() throws Exception { + doTestXml("]> "); + } + + public void testNewParsing7() throws Exception { + doTestXml(" "); + } + + public void testNewParsing8() throws Exception { + doTestXml(""); + } + + public void testNewParsing9() throws Exception { + doTestXml(""); + } + + public void testNewParsing10() throws Exception { + doTestXml(" "); + } + + public void testNewParsing11() throws Exception { + doTestXml(" "); + } + + public void testNewParsing12() throws Exception { + doTestXml(""); + } + + public void testNewParsing13() throws Exception { + doTestXml("\n" + "xxx \n" + "xxxx\n" + "<"); + } + + public void testNewParsing14() throws Exception { + doTestXml(""); + } + + public void testNewParsing15() throws Exception { + doTestXml("]> "); + } + + public void testNewParsing19() throws Exception { + doTestXml("" + "]>\n" + + " "); + } + + public void testNewParsing20() throws Exception { + doTestXml("\n" + "\n" + "\n" + ""); + } + + public void testEntityInAttr() throws Exception { + doTestXml(""); + } + + public void testEntityInContent() throws Exception { + doTestXml(" &n "); + } + + public void testMultyRoots() throws Exception { + doTestXml(" "); + } + + public void testMultyRootsWithErrorsBetween() throws Exception { + doTestXml(" "); + } + + public void testGtInTagContent() throws Exception { + doTestXml(">"); + } + + public void testManyErrors() throws Exception { + doTestXml(loadFile("manyErrors.xml")); + } + + public void _testLexerPerformance1() throws Exception{ + final String text = loadFile("pallada.xml"); + XmlLexer lexer = new XmlLexer(); + doLex(lexer, text); + final FilterLexer filterLexer = new FilterLexer(new XmlLexer(), + new FilterLexer.SetFilter(LanguageParserDefinitions.INSTANCE.forLanguage(XMLLanguage.INSTANCE).getWhitespaceTokens())); + doLex(filterLexer, text); + doLex(lexer, text); + doLex(filterLexer, text); + doLex(filterLexer, text); + } + + public void _testLexerPerformance2() throws Exception{ + final String text = loadFile("performance2.xml"); + XmlLexer lexer = new XmlLexer(); + doLex(lexer, text); + final FilterLexer filterLexer = new FilterLexer(new XmlLexer(), + new FilterLexer.SetFilter(LanguageParserDefinitions.INSTANCE.forLanguage(XMLLanguage.INSTANCE).getWhitespaceTokens())); + doLex(filterLexer, text); + doLex(lexer, text); + for (int i = 0; i < 20; i++) { + doLex(filterLexer, text); + } + } + + private static void doLex(Lexer lexer, final String text) { + lexer.start(text); + long time = System.currentTimeMillis(); + int count = 0; + while(lexer.getTokenType() != null){ + lexer.advance(); + count++; + } + System.out.println("Plain lexing took " + (System.currentTimeMillis() - time) + "ms lexems count:" + count); + } + + private void transformAllChildren(final ASTNode file) { + for (ASTNode child = file.getFirstChildNode(); child != null; child = child.getTreeNext()) { + transformAllChildren(child); + } + } + + + public void _testPerformance1() throws Exception{ + final String text = loadFile("pallada.xml"); + long time = System.currentTimeMillis(); + final PsiFile file = createFile("test.xml", text); + transformAllChildren(file.getNode()); + System.out.println("Old parsing took " + (System.currentTimeMillis() - time) + "ms"); + int index = 0; + while(index++ < 10){ + newParsing(text); + } + LeafElement firstLeaf = TreeUtil.findFirstLeaf(file.getNode()); + index = 0; + do{ + index++; + } + while((firstLeaf = TreeUtil.nextLeaf(firstLeaf, null)) != null); + System.out.println("For " + index + " lexems"); + } + + public void _testReparsePerformance() throws Exception { + final String text = loadFile("performance2.xml"); + final PsiFile file = createFile("test.xml", text); + transformAllChildren(file.getNode()); + final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(file); + + System.gc(); + System.gc(); + + new WriteCommandAction(getProject(), file) { + @Override + protected void run(final Result result) throws Throwable { + PlatformTestUtil.startPerformanceTest("XML reparse using PsiBuilder", 2500, new ThrowableRunnable() { + @Override + public void run() throws Exception { + for (int i = 0; i < 10; i++) { + final long tm = System.currentTimeMillis(); + doc.insertString(0, ""); + PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); + System.out.println("Reparsed for: " + (System.currentTimeMillis() - tm)); + } + } + }).cpuBound().assertTiming(); + } + }.execute(); + } + + public void _testPerformance2() throws Exception{ + final String text = loadFile("performance2.xml"); + long time = System.currentTimeMillis(); + final PsiFile file = createFile("test.xml", text); + transformAllChildren(file.getNode()); + System.out.println("Old parsing took " + (System.currentTimeMillis() - time) + "ms"); + int index = 0; + while(index++ < 10){ + newParsing(text); + } + LeafElement firstLeaf = TreeUtil.findFirstLeaf(file.getNode()); + index = 0; + do{ + index++; + } + while((firstLeaf = TreeUtil.nextLeaf(firstLeaf, null)) != null); + System.out.println("For " + index + " lexems"); + } + + private static void newParsing(final String text) { + long time = System.currentTimeMillis(); + + ASTFactory.lazy(XmlElementType.XML_FILE, text).getFirstChildNode(); // ensure parsed + + System.out.println("parsed for " + (System.currentTimeMillis() - time) + "ms"); + } + + public void testXmlDecl() throws Exception { + doTestXml(""); + } + + public void testXmlDecl2() throws Exception { + doTestXml(" "); + } + + public void testXmlDecl3() throws Exception { + doTestXml(" "); + } + + public void testDoctype1() throws Exception { + doTestXml(""); + } + + public void testDoctype2() throws Exception { + doTestXml(""); + } + + public void testDoctype3() throws Exception { + doTestXml("" + "]>"); + } + + public void testDoctype4() throws Exception { + doTestXml("" + "]>"); + } + + public void testDoctype5() throws Exception { + doTestXml("" + "]>"); + } + + public void testDoctype6() throws Exception { + doTestXml("" + "]>"); + } + + public void testDoctype7() throws Exception { + doTestXml("" + "" + "" + ""); + } + + public void testAttlist1() throws Exception { + doTestDtd(""); + } + + public void testAttlist2() throws Exception { + doTestDtd(""); + } + + public void testAttlist3() throws Exception { + doTestDtd(""); + } + + public void testAttlist4() throws Exception { + doTestDtd(""); + } + + public void testComment1() throws Exception { + doTestXml(""); + } + + public void testComment2() throws Exception { + doTestDtd(" "); + } + + public void testElements1() throws Exception { + doTestXml(""); + } + + public void testElements2() throws Exception { + doTestXml(""); + } + + public void testElements3() throws Exception { + doTestXml(""); + } + + public void testElements4() throws Exception { + doTestXml("\n" + "\n" + "\n" + + "\n"); + } + + public void testElements5() throws Exception { + doTestXml(""); + } + + public void testElements6() throws Exception { + doTestXml("" + "]>" + "" + ""); + } + + public void testAttributes1() throws Exception { + doTestXml(""); + } + + public void testAttributes2() throws Exception { + doTestXml(" "); + } + + public void testAttributes3() throws Exception { + doTestXml(" "); + } + + public void testAttributes4() throws Exception { + doTestXml(" "); + } + + public void testAttributes5() throws Exception { + doTestXml(" "); + } + + public void testManualEmptyAttributeParsing() throws Exception{ + String value = " "; + final CompositeElement element = parseManually(value, XmlElementType.XML_ELEMENT_DECL, XmlEntityDecl.EntityContextType.GENERIC_XML); + checkResult("testManualEmptyAttributeParsing.txt", DebugUtil.treeToString(element, false)); + } + + private CompositeElement parseManually(final String value, final IElementType xmlElementDecl, XmlEntityDecl.EntityContextType parseType) { + return (CompositeElement)new OldXmlParser(value, xmlElementDecl, parseType, new CharTableImpl(), getPsiManager()).parse(); + } + + public void testCharacters1() throws Exception { + doTestXml("someChar\nData"); + } + + public void testEditing1() throws Exception { + doTestXml("<"); + } + + public void testEditing2() throws Exception { + doTestXml(" < "); + } + + public void testEditing3() throws Exception { + doTestXml(""); + } + + public void testEditing4() throws Exception { + doTestXml("< "); + } + + public void testEditing5() throws Exception { + doTestXml(""); + } + + public void testEditing6() throws Exception { + doTestXml(" "); + } + + public void testEditing7() throws Exception { + doTestXml(" "); + } + + public void testEditing8() throws Exception { + doTestXml(" "); + } + + public void testEditing9() throws Exception { + doTestXml(" ashdgjkasgd "); + } + + + public void testCdata1() throws Exception { + doTestXml("Hello, world!]]>"); + } + + public void testCdata2() throws Exception { + doTestXml("--> more data]]>"); + } + + public void testDtd1() throws Exception { + doTestDtd(" "); + } + + public void testElementDecl1() throws Exception { + doTestDtd(""); + } + + public void testElementDecl2() throws Exception { + doTestDtd(""); + } + + public void testConditionalSection1() throws Exception { + doTestDtd(" ]]>"); + } + + public void testConditionalSection2() throws Exception { + doTestDtd("\n" + "]]>\n" + "]]>"); + } + + public void testConditionalSection3() throws Exception { + doTestDtd("\n" + "\n" + "%dbhier;\n" + "]]>"); + } + + public void testEntityRef1() throws Exception { + doTestXml("%types;"); + } + + public void testEntityRef3() throws Exception { + doTestDtd(""); + } + + public void testEntityRef4() throws Exception { + doTestXml(""); + } + + public void testEntityRef5() throws Exception { + doTestDtd(""); + } + + public void testEntityDecl1() throws Exception { + doTestDtd(""); + } + + public void testEntityDecl2() throws Exception { + doTestDtd(""); + } + + public void testEntityDecl3() throws Exception { + doTestDtd(""); + } + + public void testEntityDecl4() throws Exception { + doTestDtd( + ""); + } + + public void testUnbalanced1() throws Exception { + doTestXml(""); + } + + public void testUnbalanced2() throws Exception { + doTestXml(""); + } + + public void testUnbalanced3() throws Exception { + doTestXml(""); + } + + public void testUnbalanced4() throws Exception { + doTestXml(""); + } + + public void testDtdUrl1() throws Exception { + XmlFile file = (XmlFile)createFile("test.xml", ""); + + XmlDocument document = file.getDocument(); + XmlProlog prolog = document.getProlog(); + XmlDoctype doctype = prolog.getDoctype(); + String url = doctype.getDtdUri(); + assertTrue("testDtdUrl1", "hello.dtd".equals(url)); + } + + public void testContent1() throws Exception { + XmlFile file = (XmlFile)createFile("test.xml", " \nxxx \n"); + checkResult("testContent1", file); + assertTrue("xxx".equals(file.getDocument().getRootTag().getValue().getTrimmedText())); + } + + public void testUnopenedTag1() throws Exception { + doTestXml(""); + } + + public void testUnclosedTag() throws Exception { + XmlFile file = (XmlFile)createFile("test.xml", "xxx"); + checkResult("testUnclosedTag", file); + assertTrue("xxx".equals(file.getDocument().getRootTag().getValue().getText())); + } + + public void testUnclosedTag2() throws Exception { + doTestXml(""); + } + + public void testProcessingInstruction2() throws Exception { + doTestXml(""); + } + + public void testProcessingInstruction3() throws Exception { + doTestXml("" + "" + + "" + "" + "" + ""); + } + + public void testCharRef1() throws Exception { + doTestXml("{"); + } + + public void testCharRef2() throws Exception { + doTestXml("ģ"); + } + + public void testCharRef3() throws Exception { + doTestXml("{"); + } + + public void testCharRef4() throws Exception { + doTestXml("�"); + } + + public void testCharRef5() throws Exception { + doTestXml(""); + } + + public void testNotation1() throws Exception { + doTestDtd(""); + } + + public void testPrologInDtd() throws Exception { + doTestDtd("\n" + "\n" + ""); + } + + public void testEmptyElementsInDtd() throws Exception { + doTestDtd("\n " + ""); + } + + public void testElementDeclaration() throws Exception { + doTestDtd( + "\n\n\n\n"); + } + + public void testEntityDeclaration() throws Exception { + doTestDtd(" "); + } + + public void testEntityDeclaration2() throws Exception { + String s = "| %pre.qname; | %blockquote.qname; | %address.qname;"; + CompositeElement element = parseManually(s, XmlElementType.XML_ELEMENT_CONTENT_SPEC, XmlEntityDecl.EntityContextType.ELEMENT_CONTENT_SPEC); + checkResult("testEntityDeclaration2.txt", DebugUtil.treeToString(element, false)); + } + + public void testEntityInAttlistDeclaration() throws Exception { + doTestDtd(""); + } + + public void testSGMLDtd() throws Exception { + doTestDtd(" \n" + + "\n" + + ""); + } + + public void testNotation2() throws Exception { + doTestXml("]>"); + } + + +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlPerformanceTest.java b/xml/tests/src/com/intellij/codeInsight/XmlPerformanceTest.java new file mode 100644 index 000000000000..7552ad09388a --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlPerformanceTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved. + */ + +/* + * Created by IntelliJ IDEA. + * User: Maxim.Mossienko + * Date: Sep 8, 2006 + * Time: 3:40:30 PM + */ +package com.intellij.codeInsight; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.actionSystem.EditorActionManager; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * @by Maxim.Mossienko + */ +public class XmlPerformanceTest extends LightQuickFixTestCase { + private final Set ourTestsWithFolding = new HashSet(Arrays.asList("IndentUnindent2")); + + @Override + protected String getBasePath() { + return "performance/"; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/"; + } + + public void testDummy() { + @SuppressWarnings({"UnusedDeclaration"}) + Class clazz = IdeaTestUtil.class; + } + + public void testIndentUnindent() throws Exception { + doIndentTest(2000); + } + + public void testIndentUnindent2() throws Exception { + doIndentTest(2001); + } + + @Override + protected boolean doFolding() { + return ourTestsWithFolding.contains(getTestName(false)); + } + + private void doIndentTest(int time) throws Exception { + configureByFile(getBasePath() + getTestName(false)+".xml"); + doHighlighting(); + myEditor.getSelectionModel().setSelection(0,myEditor.getDocument().getTextLength()); + + PlatformTestUtil.startPerformanceTest("Fix long indent/unindent "+time, time, new ThrowableRunnable() { + @Override + public void run() { + EditorActionManager.getInstance().getActionHandler("EditorIndentSelection").execute(myEditor, new DataContext() { + @Override + @Nullable + public Object getData(String dataId) { + return null; + } + }); + + EditorActionManager.getInstance().getActionHandler("EditorUnindentSelection").execute(myEditor, new DataContext() { + @Override + @Nullable + public Object getData(String dataId) { + return null; + } + }); + } + }).assertTiming(); + final int startOffset = myEditor.getCaretModel().getOffset(); + myEditor.getSelectionModel().setSelection(startOffset,startOffset); + checkResultByFile(getBasePath() + getTestName(false)+".xml"); + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlReparseTest.java b/xml/tests/src/com/intellij/codeInsight/XmlReparseTest.java new file mode 100644 index 000000000000..08107e7a2a0b --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlReparseTest.java @@ -0,0 +1,165 @@ +/* + * Created by IntelliJ IDEA. + * User: mike + * Date: Oct 4, 2002 + * Time: 2:14:24 PM + * To change template for new class use + * Code Style | Class Templates options (Tools | IDE Options). + */ +package com.intellij.codeInsight; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.psi.AbstractReparseTestCase; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.source.xml.XmlFileImpl; +import com.intellij.psi.xml.XmlFile; +import com.intellij.testFramework.ParsingTestCase; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.IncorrectOperationException; + +import java.io.File; + +@PlatformTestCase.WrapInCommand +public class XmlReparseTest extends AbstractReparseTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + setFileType(StdFileTypes.XML); + } + + public void test1() throws Exception{ + String s1 = ""; + String s2 = ""; + + prepareFile(s1, s2); + final String beforeReparse = DebugUtil.treeToString(((XmlFileImpl)myDummyFile).getTreeElement(), true); + insert(""); + assertEquals("Tree changed after empty reparse", beforeReparse, DebugUtil.treeToString(((XmlFileImpl)myDummyFile).getTreeElement(), true)); + } + + public void testTagData1() throws Exception { + String s1 = ""; + String s2 = ""; + + prepareFile(s1, s2); + insert("x"); + insert(" "); + insert("xxxxx"); + insert("\n"); + insert("xxxxx"); + } + + public void testTagData2() throws Exception { + String s1 = "\nSomeDataHere"; + String s2 = "\n"; + + prepareFile(s1, s2); + + PsiElement element1 = ((XmlFile)myDummyFile).getDocument().getRootTag(); + + insert("x"); + insert(" "); + insert("xxxxx"); + insert("\n"); + insert("xxxxx"); + + assertSame(element1, ((XmlFile)myDummyFile).getDocument().getRootTag()); + } + + public void testTagInTag1() throws Exception { + String s1 = ""; + String s2 = ""; + + prepareFile(s1, s2); + + insert("<"); + insert("c"); + insert("/"); + insert(">"); + } + + public void testTagInTag2() throws Exception { + String s1 = ""; + String s2 = ""; + + prepareFile(s1, s2); + + insert("<"); + insert("c"); + insert(">"); + insert("\nxxx \nxxxx\n"); + insert("<"); + insert("/"); + insert("c"); + insert(">"); + } + + public void testTagInTag3() throws Exception { + String s1 = ""; + String s2 = ""; + + prepareFile(s1, s2); + + insert("<"); + insert("/"); + insert("b"); + insert(">"); + } + + public void testSCR5925() throws Exception { + String s1 = " "; + + prepareFile(s1, s2); + insert("a"); + insert("t"); + insert("t"); + insert("r"); + insert("="); + insert("\""); + } + + public void testXmlReparseProblem() throws IncorrectOperationException { + prepareFile("\n" + + " \n" + + "
\n" + + "\n" + + " \n" + + "
"); + insert("="); + } + private static final String marker = ""; + public void testXmlDeclDtd() throws Exception { + PsiFile file = createFile("x.xml", "\n" + + " \n" + + "]>\n" + + ""); + + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject()); + Document document = documentManager.getDocument(file); + + removeGarbage(document); + + documentManager.commitAllDocuments(); + String myFullDataPath = getTestDataPath() + "psi/"; + ParsingTestCase.doCheckResult(myFullDataPath, file, true, "testXmlDeclDtd", false, false); + } + + private static void removeGarbage(Document document) { + int i = document.getText().indexOf(marker); + if (i==-1) return; + document.replaceString(i,i+marker.length(),""); + removeGarbage(document); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/"; + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlSchemaTest.java b/xml/tests/src/com/intellij/codeInsight/XmlSchemaTest.java new file mode 100644 index 000000000000..fc9fe64b7ec1 --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlSchemaTest.java @@ -0,0 +1,757 @@ +package com.intellij.codeInsight; + +import com.intellij.psi.PsiFile; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.xml.XmlAttributeDescriptor; +import com.intellij.xml.XmlElementDescriptor; +import com.intellij.xml.XmlNSDescriptor; +import com.intellij.xml.impl.schema.XmlElementDescriptorImpl; +import com.intellij.xml.impl.schema.XmlNSDescriptorImpl; +import com.intellij.xml.util.XmlUtil; +import org.jetbrains.annotations.NonNls; + +/** + * @author Mike + */ +public class XmlSchemaTest extends LightCodeInsightTestCase { + private XmlTag SHIP_TO; + private XmlTag UNKNOWN_TAG; + + @Override + protected void setUp() throws Exception { + super.setUp(); + SHIP_TO = XmlTestUtil.tag("shipTo", getProject()); + UNKNOWN_TAG = XmlTestUtil.tag("xxx", getProject()); + } + + public void testDocumentDescriptor1() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + ""); + + assertNotNull(NSDescriptor); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("purchaseOrder", getProject()))); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("comment", getProject()))); + assertNull(NSDescriptor.getElementDescriptor(UNKNOWN_TAG)); + } + + public void testElementDescriptor1() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + ""); + + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(XmlTestUtil.tag("purchaseOrder", getProject())); + assertEquals("purchaseOrder", elementDescriptor.getName()); + + elementDescriptor = NSDescriptor.getElementDescriptor(XmlTestUtil.tag("comment", getProject())); + assertEquals("comment", elementDescriptor.getName()); + } + + public void testElementDescriptor2() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("comment", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(0, elements.length); + + XmlAttributeDescriptor[] descriptors = elementDescriptor.getAttributesDescriptors(tag); + assertEquals(0, descriptors.length); + + assertEquals(elementDescriptor.getContentType(), XmlElementDescriptor.CONTENT_TYPE_MIXED); + } + + public void testElementDescriptor3() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(3, elements.length); + assertEquals("shipTo", elements[0].getName()); + assertEquals("billTo", elements[1].getName()); + assertEquals("items", elements[2].getName()); + + assertEquals("shipTo", elementDescriptor.getElementDescriptor(SHIP_TO, null).getName()); + assertNull(elementDescriptor.getElementDescriptor(UNKNOWN_TAG, null)); + } + + public void testElementDescriptor4() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + + assertEquals(2, attributes.length); + assertEquals("orderDate", attributes[0].getName()); + assertEquals("name", attributes[1].getName()); + + assertEquals("name", elementDescriptor.getAttributeDescriptor("name", tag).getName()); + + assertNull(elementDescriptor.getAttributeDescriptor("xxx", tag)); + } + + public void testElementDescriptor5() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag).getElementDescriptor(SHIP_TO, null); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(5, elements.length); + assertEquals("name", elements[0].getName()); + assertEquals("street", elements[1].getName()); + assertEquals("city", elements[2].getName()); + assertEquals("state", elements[3].getName()); + assertEquals("zip", elements[4].getName()); + + final XmlTag context = tag.findFirstSubTag(elements[2].getName()); + assertEquals(0, elements[2].getElementsDescriptors(context).length); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(context); + assertEquals(1, attributes.length); + assertEquals("country", attributes[0].getName()); + } + + public void testElementDescriptor6() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag).getElementDescriptor(SHIP_TO, null); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(5, elements.length); + assertEquals("name", elements[0].getName()); + assertEquals("street", elements[1].getName()); + assertEquals("city", elements[2].getName()); + assertEquals("state", elements[3].getName()); + assertEquals("zip", elements[4].getName()); + + final XmlTag context = tag.findFirstSubTag(elements[2].getName()); + assertEquals(0, elements[2].getElementsDescriptors(context).length); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(context); + assertEquals(1, attributes.length); + assertEquals("country", attributes[0].getName()); + } + + public void testElementDescriptor7() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + assertEquals(0, attributes.length); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(1, elements.length); + assertEquals("shipTo", elements[0].getName()); + } + + public void testElementDescriptor8() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(1, elements.length); + assertEquals("items", elements[0].getName()); + + assertEquals("items", elementDescriptor.getElementDescriptor(XmlTestUtil.tag("items", getProject()), null).getName()); + assertNull(elementDescriptor.getElementDescriptor(UNKNOWN_TAG, null)); + } + + public void testElementDescriptor9() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(2, elements.length); + assertEquals("title", elements[0].getName()); + assertEquals("author", elements[1].getName()); + + assertEquals("title", elementDescriptor.getElementDescriptor(XmlTestUtil.tag("title", getProject()), null).getName()); + assertNull(elementDescriptor.getElementDescriptor(UNKNOWN_TAG, null)); + } + + public void testElementDescriptor10() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + "" + + " " + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + + assertEquals(2, attributes.length); + assertEquals("isbn", attributes[0].getName()); + assertEquals("available", attributes[1].getName()); + + assertEquals("isbn", elementDescriptor.getAttributeDescriptor("isbn", tag).getName()); + + assertNull(elementDescriptor.getAttributeDescriptor("xxx", tag)); + } + + public void testElementDescriptor11() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + + assertEquals(4, elements.length); + assertEquals("shipTo", elements[0].getName()); + assertEquals("billTo", elements[1].getName()); + assertEquals("shipTo2", elements[2].getName()); + assertEquals("items", elements[3].getName()); + } + + public void testElementDescriptor15() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + + assertEquals(4, elements.length); + assertEquals("shipTo", elements[0].getName()); + assertEquals("billTo", elements[1].getName()); + assertEquals("items", elements[2].getName()); + assertEquals("shipTo2", elements[3].getName()); + } + + public void testElementDescriptor12() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + + assertEquals(3, attributes.length); + assertEquals("orderDate", attributes[0].getName()); + assertEquals("orderDate2", attributes[1].getName()); + assertEquals("name", attributes[2].getName()); + } + + public void testElementDescriptor13() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + "" + + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + final XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(0, elements.length); + } + + public void testElementDescriptor14() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + "" + + "" + + "" + + " " + + " " + + " " + + " " + + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", "http://www.deansoft.com/AddressBook", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + final XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(1, elements.length); + assertEquals("name", elements[0].getName()); + XmlAttributeDescriptor[] attrs = elements[0].getAttributesDescriptors(tag); + assertEquals(1, attrs.length); + assertEquals("orderDate", attrs[0].getName()); + XmlElementDescriptor[] element0Descriptors = elements[0].getElementsDescriptors(tag.findFirstSubTag(elements[0].getName())); + assertEquals(1, element0Descriptors.length); + assertEquals("items", element0Descriptors[0].getName()); + } + + public void testAttributeDescriptor1() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor attribute = elementDescriptor.getAttributeDescriptor("orderDate", tag); + + assertTrue(!attribute.isEnumerated()); + assertTrue(!attribute.isFixed()); + assertTrue(!attribute.isRequired()); + assertNull(attribute.getDefaultValue()); + } + + public void testAttributeDescriptorProhibited() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + assertEquals(0, attributes.length); + } + + public void testAttributeDescriptorProhibited2() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + " " + + " " + + "" + + "" + + " " + + " " + + " " + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + + XmlAttributeDescriptor[] attributes = elementDescriptor.getAttributesDescriptors(tag); + + assertEquals(1, attributes.length); + assertEquals("name", attributes[0].getName()); + } + + public void testAttributeDescriptor2() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor attribute = elementDescriptor.getAttributeDescriptor("orderDate", tag); + + assertTrue(!attribute.isEnumerated()); + assertTrue(!attribute.isFixed()); + assertTrue(attribute.isRequired()); + assertEquals(" 2002 ", attribute.getDefaultValue()); + } + + public void testAttributeDescriptor3() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor attribute = elementDescriptor.getAttributeDescriptor("orderDate", tag); + + assertTrue(!attribute.isEnumerated()); + assertTrue(attribute.isFixed()); + assertTrue(!attribute.isRequired()); + assertEquals("1 01 2001", attribute.getDefaultValue()); + } + + public void testAttributeDescriptor4() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + "" + + " " + + ""); + + final XmlTag tag = XmlTestUtil.tag("purchaseOrder", getProject()); + XmlElementDescriptor elementDescriptor = NSDescriptor.getElementDescriptor(tag); + XmlAttributeDescriptor attribute = elementDescriptor.getAttributeDescriptor("orderDate", tag); + + assertNotNull(attribute); + assertTrue(!attribute.isEnumerated()); + assertTrue(attribute.isFixed()); + assertTrue(attribute.isRequired()); + assertEquals("1 01 2001", attribute.getDefaultValue()); + } + + public void testNamespace1() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + ""); + + assertNotNull(NSDescriptor); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("purchaseOrder", getProject()))); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("comment", getProject()))); + assertNull(NSDescriptor.getElementDescriptor(UNKNOWN_TAG)); + } + + public void testNamespace2() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + " " + + " " + + " " + + "" + + "" + + ""); + + XmlTag tag = XmlTestUtil.tag("purchaseOrder", "http://www.w3.org/2001/XMLSchema", getProject()); + XmlElementDescriptorImpl elementDescriptor = (XmlElementDescriptorImpl)NSDescriptor.getElementDescriptor(tag); + + XmlElementDescriptor[] elements = elementDescriptor.getElementsDescriptors(tag); + assertEquals(1, elements.length); + assertEquals("items", elements[0].getName()); + + assertEquals("items", elementDescriptor.getElementDescriptor("items").getName()); + assertNull(elementDescriptor.getElementDescriptor("xxx")); + } + + public void testNamespace3() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + "" + + "" + + ""); + + assertNotNull(NSDescriptor); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("purchaseOrder", "http://www.w3.org/2001/XMLSchema", getProject()))); + assertNotNull(NSDescriptor.getElementDescriptor(XmlTestUtil.tag("comment", "http://www.w3.org/2001/XMLSchema", getProject()))); + assertNull(NSDescriptor.getElementDescriptor(UNKNOWN_TAG)); + } + + //public void testAny1() throws Exception { + // XmlDocumentDescriptor documentDescriptor = createDescriptorImpl( + // "" + + // " " + + // " " + + // " " + + // " " + + // " " + + // " " + + // " " + + // "" + // ); + // + // XmlFile xmlFile = (XmlFile)createFile("file.xml", + // "" + + // " " + + // "" + // ); + // + // XmlElementDescriptor rootDescriptor = documentDescriptor.getElementDescriptor(xmlFile.saveToString().getRootTag()); + // assertNotNull(rootDescriptor); + // + // XmlTag aTag = xmlFile.saveToString().getRootTag().findSubTag("a:a"); + // assertNotNull(aTag); + // XmlElementDescriptor aDescriptor = documentDescriptor.getElementDescriptor(aTag); + // assertNotNull(aDescriptor); + //} + + public void testAny2() throws Exception { + PsiFile dtdFile = createFile("test.xml", "" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + ""); + + XmlNSDescriptor NSDescriptor = new XmlNSDescriptorImpl((XmlFile)dtdFile); + + XmlFile xmlFile = (XmlFile)createFile("file.xml", + "" + + " " + + "" + ); + + XmlElementDescriptor rootDescriptor = NSDescriptor.getElementDescriptor(xmlFile.getDocument().getRootTag()); + assertNotNull(rootDescriptor); + + XmlTag aTag = xmlFile.getDocument().getRootTag().findFirstSubTag("foo:a"); + assertNotNull(aTag); + //XmlElementDescriptor aDescriptor = NSDescriptor.getElementDescriptor(aTag); + //assertNull(aDescriptor); + } + + public void testAny3() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + " " + + " " + + " " + + " " + + " " + + "" + ); + + XmlFile xmlFile = (XmlFile)createFile("file.xml", + "" + + "" + ); + + final XmlTag rootTag = xmlFile.getDocument().getRootTag(); + XmlElementDescriptor rootDescriptor = NSDescriptor.getElementDescriptor(rootTag); + assertNotNull(rootDescriptor); + + XmlAttribute attribute = rootTag.getAttribute("y:a", XmlUtil.EMPTY_URI); + assertNotNull(attribute); + XmlAttributeDescriptor aDescriptor = rootDescriptor.getAttributeDescriptor("y:a", rootTag); + assertNotNull(aDescriptor); + } + + public void testAny4() throws Exception { + XmlNSDescriptor NSDescriptor = createDescriptor( + "" + + " " + + " " + + " " + + " " + + " " + + "" + ); + + XmlFile xmlFile = (XmlFile)createFile("file.xml", + "" + + "" + ); + + final XmlTag rootTag = xmlFile.getDocument().getRootTag(); + XmlElementDescriptor rootDescriptor = NSDescriptor.getElementDescriptor(rootTag); + assertNotNull(rootDescriptor); + + XmlAttribute attribute = rootTag.getAttribute("a", XmlUtil.EMPTY_URI); + assertNotNull(attribute); + XmlAttributeDescriptor aDescriptor = rootDescriptor.getAttributeDescriptor("a", rootTag); + assertNull(aDescriptor); + + attribute = rootTag.getAttribute("a", "http://foo"); + assertNull(attribute); + attribute = rootTag.getAttribute("a", XmlUtil.ANT_URI); + assertNull(attribute); + } + + private static XmlNSDescriptor createDescriptor(@NonNls String dtdText) throws Exception { + PsiFile dtdFile = createFile("test.xml", dtdText); + + return new XmlNSDescriptorImpl((XmlFile)dtdFile); + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java b/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java new file mode 100644 index 000000000000..0241f4bc46da --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java @@ -0,0 +1,960 @@ +package com.intellij.codeInsight; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.xml.*; +import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.LocalTimeCounter; +import com.intellij.xml.util.XmlTagUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.Arrays; + +/** + * @author peter + */ +@SuppressWarnings({"ConstantConditions", "EmptyCatchBlock"}) +public class XmlTagTest extends LightCodeInsightTestCase { + private static XmlTag createTag(String value) throws IncorrectOperationException { + return XmlElementFactory.getInstance(getProject()).createTagFromText("" + value + ""); + } + + public void testGetTextValue() throws Throwable { + assertEquals("bar", createTag("bar").getValue().getText()); + } + + public void testCharRefs() throws Throwable { + String[] names = XmlTagUtil.getCharacterEntityNames(); + for (String name : names) { + XmlTag tag = createTag("foo&" + name + ";bar"); + assertEquals("foo" + XmlTagUtil.getCharacterByEntityName(name) + "bar", tag.getValue().getTrimmedText()); + } + } + + public void testLocalNSDeclarations() throws Throwable { + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final Object[] nsPrefixes = ArrayUtil.toObjectArray(tag.getLocalNamespaceDeclarations().keySet()); + Arrays.sort(nsPrefixes); + assertEquals(2, nsPrefixes.length); + assertEquals("a",nsPrefixes[1]); + assertEquals("",nsPrefixes[0]); + } + + public void testCDATA() throws Throwable { + XmlTag tag = createTag("foo&'\"]]>bar"); + assertEquals("foo<>&'\"bar", tag.getValue().getTrimmedText()); + } + + public void testWhitespacesInAttributes() throws Throwable { + XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("b"); + assertEquals("b", tag.getValue().getText()); + } + + public void testCreateChildTag() throws Throwable { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final XmlTag childTag = rootTag.createChildTag("b", "bNamespace", null, true); + assertEquals("bNamespace", childTag.getNamespace()); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + XmlTag beanTag = (XmlTag)rootTag.add(childTag); + assertEquals("bNamespace", beanTag.getNamespace()); + } + }); + } + + public void testDeleteTag() throws Throwable { + XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText(" "); + final XmlTag bTag = aTag.findFirstSubTag("b"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + bTag.delete(); + } + }); + + assertEquals(0, aTag.getSubTags().length); + } + + public void testReplaceTag() throws Throwable { + final XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final XmlTag bTag = aTag.findFirstSubTag("b"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + PsiElement cTag = bTag.replace(XmlElementFactory.getInstance(getProject()).createTagFromText("")); + assertEquals(1, aTag.getSubTags().length); + assertEquals(cTag, aTag.getSubTags()[0]); + } + }); + } + + public void testAddText() throws Exception{ + final XmlElementFactory elementFactory = XmlElementFactory.getInstance(getProject()); + final XmlTag aTag = elementFactory.createTagFromText("1"); + final XmlText displayText = elementFactory.createDisplayText("2"); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + final PsiElement psiElement = aTag.addAfter(displayText, aTag.getValue().getChildren()[0]); + assertEquals(psiElement.getContainingFile(), aTag.getContainingFile()); + } + }); + } + + public void testWhitespaceInsideTag() throws Exception { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + XmlElementFactory.getInstance(getProject()).createTagFromText("

").getValue().setText("\n"); + } + }); + } + + public void testSetAttribute_ForXhtml() throws Exception { + XmlFile xhtmlFile = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy.xhtml", ""); + final XmlTag rootTag = xhtmlFile.getDocument().getRootTag(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("foo", "bar"); + } + }); + + assertEquals(1, rootTag.getAttributes().length); + assertEquals("bar", rootTag.getAttributeValue("foo")); + assertEquals("foo", rootTag.getAttributes()[0].getName()); + } + + public void testSetAttribute() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("foo", "bar"); + } + }); + + assertEquals(1, rootTag.getAttributes().length); + assertEquals("bar", rootTag.getAttributeValue("foo")); + assertEquals("foo", rootTag.getAttributes()[0].getName()); + assertEquals("", rootTag.getText()); + } + + public void testSetAttributeWithQuotes() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final String value = "a \"b\" c"; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("foo", value); + } + }); + + assertEquals(1, rootTag.getAttributes().length); + assertEquals(value, rootTag.getAttributeValue("foo")); + assertEquals("foo", rootTag.getAttributes()[0].getName()); + assertEquals("", rootTag.getText()); + } + + public void testSetAttributeWithQuotes2() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + final String value = "'a \"b\" c'"; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("foo", value); + } + }); + + final String expected = value.replaceAll("\"", """); + assertEquals(1, rootTag.getAttributes().length); + assertEquals(expected, rootTag.getAttributeValue("foo")); + assertEquals(value, rootTag.getAttribute("foo").getDisplayValue()); + assertEquals("foo", rootTag.getAttributes()[0].getName()); + assertEquals("", rootTag.getText()); + } + + public void testSetAttributeUpdateText() throws Exception { + final String value = "a \"b\" c"; + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + + assertEquals(1, rootTag.getAttributes().length); + assertEquals(value, rootTag.getAttributeValue("foo")); + + final XmlAttribute foo = rootTag.getAttribute("foo"); + final String text = foo.getValueElement().getText(); + assertEquals("'" + value + "'", text); + + ((PsiLanguageInjectionHost)foo.getValueElement()).updateText(text); + assertEquals("", rootTag.getText()); + } + + public void testSetAttributeWithNamespaces() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("foo", "", "bar"); + } + }); + + assertEquals(2, rootTag.getAttributes().length); + assertEquals("bar", rootTag.getAttributeValue("foo")); + assertEquals("foo", rootTag.getAttributes()[1].getName()); + assertEquals("", rootTag.getText()); + } + + public void testTextEdit1() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("aaa"); + final XmlText xmlText = rootTag.getValue().getTextElements()[0]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlText.removeText(0, 3); + } + }); + + assertEquals("", rootTag.getText()); + } + + public void testTextEdit2() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("a<a"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.getValue().getTextElements()[0].removeText(0, 3); + } + }); + + assertEquals("", rootTag.getText()); + } + + public void testTextEdit3() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("a<a"); + final XmlText xmlText = rootTag.getValue().getTextElements()[0]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlText.removeText(1, 2); + } + }); + + assertEquals(1, xmlText.getChildren().length); + assertEquals("aa", rootTag.getText()); + } + + public void testTextEdit4() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("aaa"); + final XmlText xmlText = rootTag.getValue().getTextElements()[0]; + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlText.removeText(1, 2); + } + }); + + assertEquals(1, xmlText.getChildren().length); + assertEquals("aa", rootTag.getText()); + } + + public void testTextEdit5() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("xxx\nyyy"); + final XmlTag y = rootTag.findFirstSubTag("y"); + + final PsiFile file = y.getContainingFile(); + String text = y.getValue().getText(); + TextRange textRange = y.getValue().getTextRange(); + + assertEquals(text, textRange.substring(file.getText())); + + new WriteCommandAction(getProject(), file) { + @Override + protected void run(final Result result) throws Throwable { + CodeStyleManager.getInstance(getProject()).adjustLineIndent(file, y.getTextOffset()); + } + }.execute(); + + text = y.getValue().getText(); + textRange = y.getValue().getTextRange(); + + assertEquals(text, textRange.substring(file.getText())); + } + + public void testTextEdit6() throws Exception { + final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("a1c"); + final XmlTag xmlTag = rootTag.findFirstSubTag("b"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlTag.delete(); + } + }); + + assertEquals("ac", rootTag.getText()); + } + + public void testBrace() throws Exception { + final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagFromText.getValue().setText("<"); + } + }); + + assertEquals("<", tagFromText.getValue().getTextElements()[0].getValue()); + } + + public void testEmptyTextRange() throws Exception { + final String text = ""; + final String name = "test.xhtml"; + XmlTag rootTag = createTag(name, text); + TextRange textRange = rootTag.getValue().getTextRange(); + assertEquals(3, textRange.getStartOffset()); + assertEquals(3, textRange.getEndOffset()); + } + + public void testDeleteTagBetweenText() throws Exception { + final XmlTag tag = createTag("foo.xhtml", "

a

b

"); + final XmlTag div = tag.getSubTags()[0]; + new WriteCommandAction(getProject(), tag.getContainingFile()) { + @Override + protected void run(final Result result) throws Throwable { + div.delete(); + } + }.execute(); + assertEquals("

ab

", tag.getText()); + } + + private static XmlTag createTag(final String name, final String text) { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()) + .createFileFromText(name, StdFileTypes.XML, text, LocalTimeCounter.currentTime(), true); + return file.getDocument().getRootTag(); + } + + // tests whether rangemarker gets changed when texts are merged, passes + public void testRangeMarker1() throws IOException, IncorrectOperationException { + final XmlFile file = (XmlFile)createFile("file.xhtml", "1234567"); + final XmlTag root = file.getDocument().getRootTag(); + final XmlTag tag = root.findFirstSubTag("b"); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + final int offset = tag.getTextOffset(); + + Document document = PsiDocumentManager.getInstance(getProject()).getDocument(root.getContainingFile()); + RangeMarker marker = document.createRangeMarker(offset - 3, offset); + tag.delete(); + + + assertEquals(4, marker.getStartOffset()); + assertEquals(7, marker.getEndOffset()); + } + }, "", null); + } + }); + } + + // this one fails, the difference is that we do some manipulations before: move "234" before the tag + public void testRangeMarker2() throws IOException, IncorrectOperationException { + final XmlTag root = createTag("file.xhtml", "1234567"); + final XmlTag tag = root.findFirstSubTag("b"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + Document document = PsiDocumentManager.getInstance(getProject()).getDocument(root.getContainingFile()); + XmlTagChild child = tag.getValue().getChildren()[0]; + assertTrue(child instanceof XmlText && child.getText().equals("234")); + + try { + tag.getParent().addBefore(child, tag); + + assertEquals(7, tag.getTextOffset()); + RangeMarker marker = document.createRangeMarker(4, 7); + tag.delete(); + + assertEquals(4, marker.getStartOffset()); + assertEquals(7, marker.getEndOffset()); + + } + catch (IncorrectOperationException e) { + } + } + }, "", null); + } + }); + } + + // the previous test relveals one problem with text merge, "234" in fact is not merged with "1" + public void test3() throws IOException, IncorrectOperationException { + final XmlTag root = XmlElementFactory.getInstance(getProject()).createTagFromText("1234456"); + final XmlTag tag = root.findFirstSubTag("b"); + + final XmlTagChild child = tag.getValue().getChildren()[0]; + assertTrue(child instanceof XmlText && child.getText().equals("234")); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + assertNotNull(tag.getParent().addBefore(child, tag)); + tag.delete(); + } + }); + + + assertEquals(1, root.getValue().getChildren().length); + assertEquals("1234456", root.getValue().getChildren()[0].getText()); + } + + public void test3XHTML() throws IOException, IncorrectOperationException { + final XmlTag root = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("1234456"); + final XmlTag tag = root.findFirstSubTag("b"); + + final XmlTagChild child = tag.getValue().getChildren()[0]; + assertTrue(child instanceof XmlText && child.getText().equals("234")); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + assertNotNull(tag.getParent().addBefore(child, tag)); + tag.delete(); + } + }); + + + assertEquals(1, root.getValue().getChildren().length); + assertEquals("1234456", root.getValue().getChildren()[0].getText()); + } + + public void testDisplayText() throws Throwable { + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(" "); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tag.add(XmlElementFactory.getInstance(getProject()).createDisplayText("aaa\nbbb")); + } + }); + + assertEquals("aaa\nbbb", tag.getValue().getTextElements()[0].getValue()); + } + + public void testXHTMLAddBefore1() throws Exception { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", + "a 123 c"); + final XmlTag tagB = file.getDocument().getRootTag().findFirstSubTag("b"); + + final XmlTagChild[] tagElements = tagB.getValue().getChildren(); + final PsiElement parent = tagB.getParent(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + PsiElement first = parent.addBefore(tagElements[0], tagB); + assertNotNull(first); + } + }); + } + + public void testXHTMLSetAttribute1() throws Exception { + new WriteCommandAction.Simple(getProject()) { + @Override + protected void run() throws Throwable { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", ""); + final XmlTag tagB = file.getDocument().getRootTag(); + + tagB.setAttribute("a", ""); + assertEquals("", tagB.getText()); + + tagB.setAttribute("b", ""); + assertEquals("", tagB.getText()); + + tagB.setAttribute("c", ""); + assertEquals("", tagB.getText()); + + tagB.getAttributes()[1].delete(); + assertEquals("", tagB.getText()); + } + }.execute().throwException(); + } + + public void testXHTMLNbsp1() throws Exception { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xhtml", " "); + final XmlTag tagB = file.getDocument().getRootTag(); + assertEquals(tagB.getValue().getTextElements().length, 1); + assertEquals(tagB.getValue().getTextElements()[0].getValue(), "\u00a0"); + } + + public void testDeleteTagWithMultilineWhitespace1() throws Exception { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("test.xml", + "\n \n"); + final XmlTag tagB = file.getDocument().getRootTag(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagB.getSubTags()[0].delete(); + } + }); + + assertEquals("\n ", tagB.getText()); + } + + public void testDeleteTagWithMultilineWhitespace2() throws Exception { + final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()) + .createFileFromText("test.xml", "\n \n \n hasgdgasjdgasdg asgdjhasgd\n \n"); + final XmlTag tagB = file.getDocument().getRootTag(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagB.getSubTags()[0].getSubTags()[0].delete(); + } + }); + + assertEquals("\n \n \n", tagB.getText()); + } + + public void testXHTMLRangeMarkers2() throws Exception { + XmlTag tag = createTag("file.xhtml", "xyz"); + PsiFile psiFile = tag.getContainingFile(); + Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile); + RangeMarker rangeMarker = document.createRangeMarker(5, 5); + final XmlText text = (XmlText) tag.getValue().getChildren()[0]; + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + try{ + text.removeText(2, 3); + } + catch(IncorrectOperationException ioe){} + } + }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); + } + }); + + assertEquals(5, rangeMarker.getStartOffset()); + assertEquals(5, rangeMarker.getEndOffset()); + } + + public void testXHTMLTextInsert() throws Exception { + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("xyz"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tag.getValue().getTextElements()[0].insertText("<", 1); + } + }); + + assertEquals("x<yz", tag.getText()); + } + + public void testSimpleTextInsertion() throws Throwable { + doTestSimpleInsertion("xyz", "a"); + doTestSimpleInsertion(" xyz", "a"); + doTestSimpleInsertion("x yz", "a"); + doTestSimpleInsertion("xy z", "a"); + doTestSimpleInsertion("xyz ", "a"); + doTestSimpleInsertion(" xyz ", "a"); + doTestSimpleInsertion(" x y z ", "a"); + } + + public void testWhitespaceTextInsertion() throws Throwable { + doTestSimpleInsertion("xyz", " "); + } + + public void testSimpleTextDeletion() throws Throwable { + doTestSimpleDeletion("xyz"); + doTestSimpleDeletion(" xyz"); + doTestSimpleDeletion("x yz"); + doTestSimpleDeletion("xy z"); + doTestSimpleDeletion("xyz "); + doTestSimpleDeletion(" xyz "); + doTestSimpleDeletion(" x y z "); + } + + public void testWhitespaceDeletion() throws Throwable { + doTestSimpleDeletion(" xyz"); + doTestSimpleDeletion("x yz"); + doTestSimpleDeletion("xy z"); + doTestSimpleDeletion("xyz "); + doTestSimpleDeletion(" xyz "); + doTestSimpleDeletion(" x y z "); + } + + private static void doTestSimpleDeletion(final String text) throws IncorrectOperationException { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + for (int i = 0; i < text.length(); i++) { + for (int j = i; j < text.length(); j++) { + XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("" + text + ""); + final PsiElement[] children = tag.getValue().getTextElements(); + assertEquals(1, children.length); + final XmlText xmlText = (XmlText)children[0]; + assertEquals(text, xmlText.getText()); + xmlText.removeText(i, j); + final StringBuffer expected = new StringBuffer(text); + expected.delete(i, j); + assertEquals(expected.toString(), xmlText.getValue()); + } + } + } + }); + } + + private static void doTestSimpleInsertion(final String text, final String textToInsert) throws IncorrectOperationException { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + for (int i = 0; i <= text.length(); i++) { + XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("" + text + ""); + final PsiElement[] children = tag.getValue().getTextElements(); + assertEquals(1, children.length); + final XmlText xmlText = (XmlText)children[0]; + assertEquals(text, xmlText.getValue()); + xmlText.insertText(textToInsert, i); + final StringBuffer expected = new StringBuffer(text); + expected.insert(i, textToInsert); + assertEquals(expected.toString(), xmlText.getValue()); + } + } + }); + } + + public void testEscapedInsertion() throws Throwable { + doTestEscapedInsertion("xyz", "&"); + doTestEscapedInsertion("xyz", "&&"); + doTestEscapedInsertion("xyz", "&x&"); + doTestEscapedInsertion("&xyz", "a"); + doTestEscapedInsertion("&xyz", " "); + doTestEscapedInsertion("x&yz", "a"); + doTestEscapedInsertion("x&yz", " "); + doTestEscapedInsertion("xy&z", "a"); + doTestEscapedInsertion("xy&z", " "); + doTestEscapedInsertion("xyz&", "a"); + doTestEscapedInsertion("xyz&", " "); + doTestEscapedInsertion("&x&y&z&", "a"); + doTestEscapedInsertion(" x&y&z&", "a"); + doTestEscapedInsertion(" x y&z&", "a"); + doTestEscapedInsertion("&x y&z&", "a"); + doTestEscapedInsertion("&x y&z ", "a"); + doTestEscapedInsertion("&x&y&z&", "<"); + doTestEscapedInsertion("&x&y&z&", ">"); + doTestEscapedInsertion("_xyz", "a"); + doTestEscapedInsertion("x_yz", "a"); + doTestEscapedInsertion("xy_z", "a"); + doTestEscapedInsertion("xyz_", "a"); + doTestEscapedInsertion("_xyz_", "a"); + doTestEscapedInsertion("_x_y_z_", "a"); + } + + public static void notestEscapedDeletion() throws Throwable { + doTestEscapedDeletion("&"); + doTestEscapedDeletion("&&"); + doTestEscapedDeletion(" &&"); + doTestEscapedDeletion(" & &"); + doTestEscapedDeletion(" & & "); + doTestEscapedDeletion(" && "); + doTestEscapedDeletion("&& "); + doTestEscapedDeletion("& "); + doTestEscapedDeletion(" "); + doTestEscapedDeletion("&abc"); + doTestEscapedDeletion("a&bc"); + doTestEscapedDeletion("ab&c"); + doTestEscapedDeletion("abc&"); + doTestEscapedDeletion(" &abc"); + doTestEscapedDeletion("a &bc"); + doTestEscapedDeletion("ab &c"); + doTestEscapedDeletion("abc &"); + doTestEscapedDeletion("& abc"); + doTestEscapedDeletion("a& bc"); + doTestEscapedDeletion("ab& c"); + doTestEscapedDeletion("abc& "); + } + + private static void doTestEscapedInsertion(final String text, final String textToInsert) throws IncorrectOperationException { + String tagText = toEscapedText(text); + for (int i = 0; i <= text.length(); i++) { + XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("" + tagText + ""); + final PsiElement[] children = tag.getValue().getTextElements(); + assertEquals(1, children.length); + final XmlText xmlText = (XmlText)children[0]; + assertEquals(tagText, xmlText.getText()); + xmlText.insertText(textToInsert, i); + final StringBuffer expectedDisplay = new StringBuffer(text.replace('_', '\u00a0')); + expectedDisplay.insert(i, textToInsert); + assertEquals(expectedDisplay.toString(), xmlText.getValue()); + +// final String expectedText = toEscapedText(expectedDisplay.toString()); +// assertEquals(expectedText, xmlText.getText()); + } + } + + private static void doTestEscapedDeletion(final String text) throws IncorrectOperationException { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + String tagText = toEscapedText(text); + for (int i = 0; i < text.length(); i++) { + for (int j = i; j < text.length(); j++) { + XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("" + tagText + ""); + final PsiElement[] children = tag.getValue().getTextElements(); + assertEquals(1, children.length); + final XmlText xmlText = (XmlText)children[0]; + assertEquals(tagText, xmlText.getText()); + xmlText.removeText(i, j); + final StringBuffer expectedDisplay = new StringBuffer(text.replace('_', ' ')); + expectedDisplay.delete(i, j); + assertEquals(expectedDisplay.toString(), xmlText.getValue()); + + final String expectedText = toEscapedText(expectedDisplay.toString()); + assertEquals(expectedText, xmlText.getText()); + } + } + } + }); + } + + public void testWhitespacesInEmptyXHTMLTag() throws Exception{ + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText(" "); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tag.findFirstSubTag("b").delete(); + } + }); + + assertEquals(" ", tag.getText()); + } + + public void test2() throws Exception { + XmlFile file = (XmlFile)createFile("file.xml", "x y"); + XmlTag tag = file.getDocument().getRootTag(); + final XmlText xmlText = tag.getValue().getTextElements()[0]; + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + try { + xmlText.insertText("z", 1); + } + catch (IncorrectOperationException e) { + throw new RuntimeException(e); + } + } + }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); + } + }); + assertEquals("xz y", tag.getText()); + } + + private static String toDisplay(String text) { + text = text.replaceAll("<", "<"); + text = text.replaceAll(">", ">"); + text = text.replaceAll("&", "&"); + text = text.replaceAll("'", "'"); + text = text.replaceAll(""", "\""); + text = text.replaceAll("", ""); + return text.replaceAll(" ", "_"); + } + + private static String toEscapedText(String original) { + String text = original.replaceAll("<", "<"); + text = text.replaceAll(">", ">"); + text = text.replaceAll("&", "&"); + text = text.replaceAll("'", "'"); + text = text.replaceAll("\"", """); + text = text.replaceAll("_", " "); + assertEquals(original, toDisplay(text)); + return text; + } + + public void testCoordinateMappingConsistent() throws Exception { + doCoordinateMappingConsistentFromDisplayText("abc"); + doCoordinateMappingConsistentFromDisplayText(" abc"); + doCoordinateMappingConsistentFromDisplayText(" a bc"); + doCoordinateMappingConsistentFromDisplayText(" a b c"); + doCoordinateMappingConsistentFromDisplayText(" a b c "); + doCoordinateMappingConsistentFromDisplayText(" ab c "); + doCoordinateMappingConsistentFromDisplayText(" abc "); + doCoordinateMappingConsistentFromDisplayText("abc "); + + doCoordinateMappingConsistentFromDisplayText(" "); + doCoordinateMappingConsistentFromDisplayText("&"); + + doCoordinateMappingConsistentFromDisplayText("&abc"); + doCoordinateMappingConsistentFromDisplayText(" &abc"); + doCoordinateMappingConsistentFromDisplayText(" a& bc"); + doCoordinateMappingConsistentFromDisplayText(" a &b c"); + doCoordinateMappingConsistentFromDisplayText(" a b& c "); + doCoordinateMappingConsistentFromDisplayText(" ab c& "); + doCoordinateMappingConsistentFromDisplayText(" ab&c "); + doCoordinateMappingConsistentFromDisplayText("abc &"); + doCoordinateMappingConsistentFromDisplayText("abc&"); + doCoordinateMappingConsistentFromDisplayText("ab&c&"); + doCoordinateMappingConsistentFromDisplayText("ab&c"); + doCoordinateMappingConsistentFromDisplayText("a&b&c"); + + doCoordinateMappingConsistentFromEscapedText(""); + doCoordinateMappingConsistentFromEscapedText(""); + doCoordinateMappingConsistentFromEscapedText("xxx"); + doCoordinateMappingConsistentFromEscapedText("xxxxxx"); + doCoordinateMappingConsistentFromEscapedText("xxx&xxx"); + doCoordinateMappingConsistentFromEscapedText("xxx&&xxx"); + doCoordinateMappingConsistentFromEscapedText("xxx&xxx"); + doCoordinateMappingConsistentFromEscapedText("xxx&xxx"); + doCoordinateMappingConsistentFromEscapedText("xxxs]]>&xxx"); + doCoordinateMappingConsistentFromEscapedText("xxxs]]>&xxx"); + } + + public void testNBSP() throws Exception { + final XmlTag tagA = XmlElementFactory.getInstance(getProject()).createXHTMLTagFromText("1 "); + + final XmlTag tagB = tagA.findFirstSubTag("b"); + final XmlTagChild nbsp = tagB.getValue().getChildren()[0]; + assertEquals(" ", nbsp.getText()); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tagA.addBefore(nbsp.copy(), tagB); + } + }); + + XmlTagChild nbsp1 = tagA.getValue().getChildren()[0]; + assertEquals("1 ", nbsp1.getText()); + } + + private static void doCoordinateMappingConsistentFromDisplayText(final String text) throws IncorrectOperationException { + doCoordinateMappingConsistentFromEscapedText(toEscapedText(text)); + } + + private static void doCoordinateMappingConsistentFromEscapedText(final String tagText) throws IncorrectOperationException { + String text = toDisplay(tagText); + XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("" + tagText + ""); + final PsiElement[] children = tag.getValue().getTextElements(); + assertEquals(1, children.length); + final XmlText xmlText = (XmlText)children[0]; + assertEquals(tagText, xmlText.getText()); + + for (int i = 0; i <= text.length(); i++) { + final int physical = xmlText.displayToPhysical(i); + final int display = xmlText.physicalToDisplay(physical); + assertEquals("Coords mapping failed for: '" + tagText + "' - " + physical, display, i); + } + + assertEquals("Coords mapping failed for: '" + tagText + "'", 0, xmlText.physicalToDisplay(0)); + assertEquals(tagText.length(), xmlText.displayToPhysical(text.length())); + assertEquals(text.length(), xmlText.physicalToDisplay(tagText.length())); + } + + public void testStrangeCharactesInText() throws Throwable { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + XmlElementFactory.getInstance(getProject()).createTagFromText("").getValue().setText("@#$%@$%$${${''}"); + } + }); + } + + public void testPsiToDocumentSynchronizationFailed() throws Throwable { + String text = " "; + final File tempFile = FileUtil.createTempFile("idea-test", ".xml"); + tempFile.createNewFile(); + final FileOutputStream fileOutputStream = new FileOutputStream(tempFile); + fileOutputStream.write(text.getBytes()); + fileOutputStream.flush(); + fileOutputStream.close(); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + @SuppressWarnings({"ConstantConditions"}) + public void run() { + VirtualFileManager.getInstance().refresh(false); + XmlFile file ;//createTemporaryFile("wpd.xml", text)); + try { + file = (XmlFile)getPsiManager().findFile(VfsUtil.findFileByURL(tempFile.toURL())); + } + catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + final XmlTag methodTag = file.getDocument().getRootTag().findFirstSubTag("methods"); + try { + methodTag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("")); + } + catch (IncorrectOperationException e) { + throw new RuntimeException(e); + } + } + }, "", null, UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION); + } + }); + } + + public void testXmlFormattingException() throws Throwable { + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("bar"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tag.add(XmlElementFactory.getInstance(getProject()).createTagFromText("")); + } + }); + } + + public void testSetNamespace() throws Exception { + XmlFile xhtmlFile = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy.xml", + ""); + + final XmlTag rootTag = xhtmlFile.getDocument().getRootTag(); + + rootTag.getSubTags()[0].getNamespace(); // fill the cache + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + rootTag.setAttribute("xmlns", "http://www.ru"); + } + }); + + assertEquals("http://www.ru", rootTag.getSubTags()[0].getNamespace()); + } + + public void testInsert() throws Exception { + String html = "
\n"; + XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("xxx.xhtml", html); + XmlTag body = file.getDocument().getRootTag().findFirstSubTag("body"); + final XmlTag hr = body.getSubTags()[0]; + + final XmlText text = XmlElementFactory.getInstance(getProject()).createDisplayText("p"); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + PsiElement element = hr.getParentTag().addAfter(text, hr); + assertEquals(element.getParent(), hr.getParentTag()); + } + }); + } + + public void testCollapse() throws IncorrectOperationException { + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + tag.collapseIfEmpty(); + assertEquals("", tag.getText()); + + final XmlTag tag1 = XmlElementFactory.getInstance(getProject()).createTagFromText("abc"); + tag1.collapseIfEmpty(); + assertEquals("", tag1.getText()); + + final XmlTag tag2 = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + tag2.collapseIfEmpty(); + assertEquals("", tag2.getText()); + } + }); + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java b/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java new file mode 100644 index 000000000000..7728fe5edadf --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java @@ -0,0 +1,61 @@ +package com.intellij.codeInsight; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.psi.XmlElementFactory; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlText; +import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.util.IncorrectOperationException; +import com.intellij.xml.util.XmlUtil; + +/** + * @author lesya, dsl + */ +public class XmlTagWriteTest extends LightCodeInsightTestCase{ + public void test1() throws IncorrectOperationException { + XmlElementFactory elementFactory = XmlElementFactory.getInstance(getProject()); + final XmlTag xmlTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlTag.add(xmlTag.createChildTag("tag2", XmlUtil.EMPTY_URI, null, false)); + } + }); + + + assertEquals("", xmlTag.getText()); + XmlTag createdFromText = elementFactory.createTagFromText(xmlTag.getText()); + assertEquals("tag1", createdFromText.getName()); + assertEquals(1, createdFromText.getSubTags().length); + assertEquals("tag2", createdFromText.getSubTags()[0].getName()); + } + + public void test2() throws IncorrectOperationException { + final XmlTag xmlTag = XmlElementFactory.getInstance(getProject()).createTagFromText(""); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + xmlTag.add(xmlTag.createChildTag("tag2", XmlUtil.EMPTY_URI, null, false)); + } + }); + + + assertEquals("", xmlTag.getText()); + XmlTag createdFromText = XmlElementFactory.getInstance(getProject()).createTagFromText(xmlTag.getText()); + assertEquals("tag1", createdFromText.getName()); + assertEquals(1, createdFromText.getSubTags().length); + assertEquals("tag2", createdFromText.getSubTags()[0].getName()); + } + + public void test3() throws Exception{ + final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText("\n0123456"); + final XmlText text = (XmlText) tag.getValue().getChildren()[0]; + String textS = text.getText(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + text.insertText("lala", 2); + } + }); + + XmlText text2 = (XmlText)tag.getValue().getChildren()[0]; + assertEquals(textS.substring(0, 2) + "lala" + textS.substring(2), text2.getText()); + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTestUtil.java b/xml/tests/src/com/intellij/codeInsight/XmlTestUtil.java new file mode 100644 index 000000000000..75aa8825cc68 --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlTestUtil.java @@ -0,0 +1,22 @@ +package com.intellij.codeInsight; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.annotations.NonNls; + +public class XmlTestUtil { + + public static XmlTag tag(@NonNls String tagName, Project project) throws Exception { + XmlFile file = (XmlFile)PsiFileFactory.getInstance(project).createFileFromText("tag.xml", "<" + tagName + "/>"); + return file.getDocument().getRootTag(); + } + + public static XmlTag tag(@NonNls String tagName, @NonNls String namespace, Project project) throws Exception { + XmlFile file = (XmlFile)PsiFileFactory.getInstance(project) + .createFileFromText("tag.xml", "<" + tagName + " xmlns=\"" + namespace + "\"/>"); + return file.getDocument().getRootTag(); + } + +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTextTest.java b/xml/tests/src/com/intellij/codeInsight/XmlTextTest.java new file mode 100644 index 000000000000..55cdc25e4aa8 --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlTextTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved. + */ + +package com.intellij.codeInsight; + +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.XmlElementFactory; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlText; +import com.intellij.testFramework.LightCodeInsightTestCase; + +/** + * @author mike + */ +public class XmlTextTest extends LightCodeInsightTestCase { + public void testInsertAtOffset() throws Exception { + new WriteCommandAction(getProject()) { + + @Override + protected void run(final Result result) throws Throwable { + String xml = "0123456789"; + XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()) + .createFileFromText("foo.xml", StdFileTypes.XML, xml, (long)1, true, false); + //System.out.println(DebugUtil.psiToString(file, false)); + XmlTag root = file.getDocument().getRootTag(); + final XmlText text1 = root.getValue().getTextElements()[0]; + + assertFalse(CodeEditUtil.isNodeGenerated(root.getNode())); + final XmlText text = text1; + + final XmlElement element = text.insertAtOffset(XmlElementFactory.getInstance(getProject()).createTagFromText(""), 5); + assertNotNull(element); + assertTrue(element instanceof XmlText); + assertEquals("01234", element.getText()); + assertEquals("0123456789", text.getContainingFile().getText()); + } + }.execute(); + } + + public void testPhysicalToDisplayIfHasGaps2() throws Exception { + String xml = "
&abc
"; + XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("foo.xml", xml); + XmlTag root = file.getDocument().getRootTag(); + final XmlText text = root.getValue().getTextElements()[0]; + + assertEquals("&abc", text.getValue()); + assertEquals(0, text.physicalToDisplay(0)); + assertEquals(1, text.physicalToDisplay(5)); + assertEquals(2, text.physicalToDisplay(6)); + assertEquals(3, text.physicalToDisplay(7)); + assertEquals(4, text.physicalToDisplay(8)); + } + + public void testDisplayToPhysical() throws Exception { + String xml = "
&abc
"; + XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("foo.xml", xml); + XmlTag root = file.getDocument().getRootTag(); + final XmlText text = root.getValue().getTextElements()[0]; + + assertEquals("&abc", text.getValue()); + assertEquals(0, text.displayToPhysical(0)); + assertEquals(5, text.displayToPhysical(1)); + assertEquals(6, text.displayToPhysical(2)); + assertEquals(7, text.displayToPhysical(3)); + assertEquals(8, text.displayToPhysical(4)); + } + + public void testDisplayToPhysical2() throws Exception { + String xml = "
"; + XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("foo.xml", xml); + XmlTag root = file.getDocument().getRootTag(); + final XmlText text = root.getValue().getTextElements()[0]; + + assertEquals(" ", text.getValue()); + assertEquals(9, text.displayToPhysical(0)); + assertEquals(13, text.displayToPhysical(1)); + } + +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java b/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java new file mode 100644 index 000000000000..66db22990a8c --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java @@ -0,0 +1,23 @@ +package com.intellij.codeInsight; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; +import com.intellij.testFramework.PlatformTestUtil; + +import java.io.File; + +/** + * @author spleaner + */ +public class XmlWrongClosingTagNameInspectionTest extends LightQuickFixTestCase { + public void test() throws Exception { doAllTests(); } + + @Override + protected String getBasePath() { + return "/wrongClosingTagName"; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/inspections"; + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/XmlXIncludeTest.groovy b/xml/tests/src/com/intellij/codeInsight/XmlXIncludeTest.groovy new file mode 100644 index 000000000000..161eda9f3236 --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/XmlXIncludeTest.groovy @@ -0,0 +1,99 @@ +package com.intellij.codeInsight; + + +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.xml.XmlFile +import com.intellij.psi.xml.XmlTag +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.application.WriteAction + +/** + * @author mike + */ +public class XmlXIncludeTest extends LightCodeInsightFixtureTestCase { + private static final String BASE_PATH = "/psi/xi"; + + public void testBasicXi() throws Exception { + configure(); + assertSubtagNames("before", "include1", "after"); + } + + public void testXpointerXi1() throws Exception { + configure(); + assertSubtagNames("before", "foo", "bar", "after"); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/" + BASE_PATH; + } + + private void assertSubtagNames(String... expectedNames) { + final XmlTag tag = ((XmlFile)myFixture.file).document.rootTag + final List names = tag.getSubTags().collect { it.name } + + assertEquals( + "subtags are different", + StringUtil.join(expectedNames, "\n"), StringUtil.join(names, "\n") + ); + } + + private void configure() throws Exception { + myFixture.configureByFiles(getName() + ".xml", "/include1.xml"); + } + + public void testModifyingIncludedFile() { + myFixture.configureByText 'a.xml', ''' + + + + + +''' + def inc1 = myFixture.copyFileToProject("include1.xml") + assertSubtagNames("before", "foo", "bar", "after") + + changeText inc1, '
' + + assertSubtagNames("before", "a", "after") + } + + public void testModifyingTransitivelyIncludedFile() { + myFixture.configureByText 'a.xml', ''' + + + + + +''' + myFixture.addFileToProject("include1.xml", """ + + + + + +""") + def inc2 = myFixture.addFileToProject("include2.xml", '') + + assertSubtagNames("before", "foo", "bar", "a", "after") + + changeText inc2.virtualFile, '' + + assertSubtagNames("before", "foo", "bar", "b", "after") + + } + + private changeText(VirtualFile inc1, String s) { + def token = WriteAction.start() + try { + FileDocumentManager.instance.getDocument(inc1).setText s + PsiDocumentManager.getInstance(project).commitAllDocuments() + } + finally { + token.finish() + } + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/completion/XmlSmartEnterTest.java b/xml/tests/src/com/intellij/codeInsight/completion/XmlSmartEnterTest.java new file mode 100644 index 000000000000..51682c9ff124 --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/completion/XmlSmartEnterTest.java @@ -0,0 +1,121 @@ +package com.intellij.codeInsight.completion; + +import com.intellij.codeInsight.CodeInsightSettings; +import com.intellij.codeInsight.lookup.Lookup; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.lookup.impl.LookupImpl; +import com.intellij.codeInsight.lookup.impl.LookupManagerImpl; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.testFramework.LightCodeInsightTestCase; +import com.intellij.testFramework.PlatformTestUtil; + +import java.io.File; + +/** + * @author spleaner + */ +@SuppressWarnings({"ALL"}) +public class XmlSmartEnterTest extends LightCodeInsightTestCase { + private static final String BASE_PATH = "/smartEnter"; + private LookupElement[] myItems; + + public void testSmartFinish1() throws Throwable { + doCompletionPopupTest(getTestName(false)); + } + + public void testSmartFinish2() throws Throwable { + boolean old = CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION; + CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = false; + try { + doCompletionPopupTest(getTestName(false)); + } + finally { + CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = old; + } + } + + public void testSmartFinish3() throws Exception { + doSmartEnterTest("SmartFinish1"); + } + + public void testSmartFinish4() throws Exception { + doSmartEnterTest("SmartFinish2"); + } + + public void testSmartFinish5() throws Exception { + doSmartEnterTest("SmartFinish3"); + } + + public void testSmartFinish_IDEADEV_29628() throws Exception { + doSmartEnterTest("IDEADEV_29628"); + } + + public void testSmartFinishWithWrongAttribute() throws Exception { + doSmartEnterTest("WrongAttribute"); + } + + public void testOpenAttribute() throws Exception { + doSmartEnterTest("OpenAttribute"); + } + + public void testComplete1() throws Exception { + _doTest("Tag.xml", "Tag_after.xml"); + } + + private void doCompletionPopupTest(String baseName) throws Exception { + _doTestCompletion(baseName + ".xml", baseName + "_after.xml"); + } + + private void _doTestCompletion(final String name, final String after_name) throws Exception { + configureByFile(BASE_PATH + "/" + name); + performCompletionAction(); + select(Lookup.COMPLETE_STATEMENT_SELECT_CHAR); + checkResultByFile(BASE_PATH + "/" + after_name); + } + + private void doSmartEnterTest(String baseName) throws Exception { + _doTest(baseName + ".xml", baseName + "_after.xml"); + } + + private void _doTest(String filename, String filename_after) throws Exception { + configureByFile(BASE_PATH + "/" + filename); + + new WriteCommandAction(getProject()) { + protected void run(final Result result) throws Throwable { + new XmlSmartEnterProcessor().process(getProject(), getEditor(), getFile()); + } + }.execute(); + + checkResultByFile("", BASE_PATH + "/" + filename_after, true); + } + + private void performCompletionAction() { + new CodeCompletionHandlerBase(CompletionType.BASIC).invokeCompletion(getProject(), getEditor()); + final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(getEditor()); + myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY); + } + + private void select(final char c) { + if (c != '\n' && c != '\t' && c != Lookup.COMPLETE_STATEMENT_SELECT_CHAR) { + type(c); + return; + } + + final LookupManagerImpl manager = (LookupManagerImpl) LookupManager.getInstance(getProject()); + final Lookup lookup = manager.getActiveLookup(); + if(lookup != null) { + manager.forceSelection(c, lookup.getCurrentItem()); + } + } + + protected String getBasePath() { + return ""; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/"; + } +} diff --git a/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java new file mode 100644 index 000000000000..8c9c78494ecd --- /dev/null +++ b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java @@ -0,0 +1,66 @@ +package com.intellij.codeInsight.editorActions.moveUpDown; + +import com.intellij.codeInsight.CodeInsightTestCase; +import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.testFramework.PlatformTestUtil; +import org.jetbrains.annotations.NonNls; + +import java.io.File; + +/** + * @author spleaner + */ +@SuppressWarnings({"ALL"}) +public class XmlMoverTest extends CodeInsightTestCase { + + public void testTag() throws Exception { doTest("xml"); } + public void testTag2() throws Exception { doTest("xml"); } + public void testTag3() throws Exception { doTest("xml"); } + public void testTag4() throws Exception { doTest("xml"); } + public void testTag5() throws Exception { doTest("xml"); } + public void testTag6() throws Exception { doTest("xml"); } + public void testTag7() throws Exception { doTest("xml"); } + public void testTag8() throws Exception { doTest("xml"); } + public void testTag9() throws Exception { doTest("xml"); } + public void testTag10() throws Exception { doTest("xml"); } + public void testTag11() throws Exception { doTest("xml"); } + + public void test1() throws Exception { doTest("html"); } + + private void doTest(String ext) throws Exception { + final String baseName = getBasePath() + '/' + getTestName(true); + final String fileName = baseName + "."+ext; + + try { + @NonNls String afterFileName = baseName + "_afterUp." + ext; + EditorActionHandler handler = new MoveStatementUpAction().getHandler(); + performAction(fileName, handler, afterFileName); + + afterFileName = baseName + "_afterDown." + ext; + handler = new MoveStatementDownAction().getHandler(); + performAction(fileName, handler, afterFileName); + } + finally { + //CodeStyleSettingsManager.getInstance(myProject).dropTemporarySettings(); + } + } + + private void performAction(final String fileName, final EditorActionHandler handler, final String afterFileName) throws Exception { + configureByFile(fileName); + final boolean enabled = handler.isEnabled(myEditor, null); + assertEquals(new File(getTestDataPath(), afterFileName).exists(), enabled); + if (enabled) { + handler.execute(myEditor, null); + checkResultByFile(afterFileName); + } + } + + protected String getBasePath() { + return "/mover"; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData"; + } +} \ No newline at end of file diff --git a/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestBase.java b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestBase.java new file mode 100644 index 000000000000..73727548743d --- /dev/null +++ b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestBase.java @@ -0,0 +1,54 @@ +package com.intellij.psi.formatter; + +import com.intellij.psi.impl.source.xml.XmlFileImpl; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.application.ApplicationManager; + +/** + * @author yole + */ +public abstract class XmlFormatterTestBase extends XmlFormatterTestCase { + protected void checkFormattingDoesNotProduceException(String name) throws Exception { + + String text = loadFile(name + ".xml", null); + final XmlFileImpl file = (XmlFileImpl)createFile(name + ".xml", text); + myTextRange = new TextRange(10000, 10001); + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + performFormatting(file); + } + }); + } + }, "", ""); + + myTextRange = new TextRange(1000000, 1000001); + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + performFormatting(file); + } + }); + } + }, "", ""); + myTextRange = new TextRange(0, text.length()); + CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + performFormatting(file); + } + }); + } + }, "", ""); + } +} diff --git a/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java new file mode 100644 index 000000000000..70cd87904c4d --- /dev/null +++ b/xml/tests/src/com/intellij/psi/formatter/XmlFormatterTestCase.java @@ -0,0 +1,25 @@ +package com.intellij.psi.formatter; + +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.xml.XmlCodeStyleSettings; + +/** + * @author peter + */ +public abstract class XmlFormatterTestCase extends FormatterTestCase{ + + public void testDontKeepLineBreaksInText() throws Throwable { + final CodeStyleSettings settings = getSettings(); + final XmlCodeStyleSettings xmlSettings = settings.getCustomSettings(XmlCodeStyleSettings.class); + settings.RIGHT_MARGIN = 15; + + settings.HTML_KEEP_LINE_BREAKS_IN_TEXT = false; + xmlSettings.XML_KEEP_LINE_BREAKS_IN_TEXT = false; + doTextTest("aaa\nbbb\nccc\nddd\n", "aaa bbb\n ccc ddd\n"); + + settings.HTML_TEXT_WRAP = CodeStyleSettings.DO_NOT_WRAP; + xmlSettings.XML_TEXT_WRAP = CodeStyleSettings.DO_NOT_WRAP; + doTextTest("aaa\nbbb\nccc\nddd\n", "aaa bbb ccc ddd\n"); + } + +} diff --git a/xml/tests/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjectionTest.java b/xml/tests/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjectionTest.java new file mode 100644 index 000000000000..2db52d88e6ed --- /dev/null +++ b/xml/tests/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjectionTest.java @@ -0,0 +1,28 @@ +package com.intellij.psi.impl.source.html; + +import com.intellij.codeInsight.completion.CompletionTestCase; +import com.intellij.testFramework.PlatformTestUtil; + +import java.io.File; + +/** + * @author spleaner + */ +@SuppressWarnings({"ALL"}) +public class HtmlConditionalCommentInjectionTest extends CompletionTestCase { + + public void testHtmlCompletion() throws Exception { + configureByFile("complete.html"); + checkResultByFile("complete_after.html"); + } + + public void testXhtmlCompletion() throws Exception { + configureByFile("complete.xhtml"); + checkResultByFile("complete_after.xhtml"); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/xml/tests/testData/commentInjection/"; + } +} diff --git a/xml/tests/src/com/intellij/xml/XmlConstraintsTest.java b/xml/tests/src/com/intellij/xml/XmlConstraintsTest.java new file mode 100644 index 000000000000..c70bc1b09aee --- /dev/null +++ b/xml/tests/src/com/intellij/xml/XmlConstraintsTest.java @@ -0,0 +1,145 @@ +package com.intellij.xml; + +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.Convertor; +import com.intellij.xml.actions.ValidateXmlActionHandler; +import org.apache.xerces.impl.Constants; +import org.apache.xerces.impl.xs.XSComplexTypeDecl; +import org.apache.xerces.impl.xs.XSElementDecl; +import org.apache.xerces.impl.xs.models.CMBuilder; +import org.apache.xerces.impl.xs.models.CMNodeFactory; +import org.apache.xerces.impl.xs.models.XSCMValidator; +import org.apache.xerces.xni.grammars.Grammar; +import org.apache.xerces.xni.grammars.XMLGrammarDescription; +import org.apache.xerces.xni.grammars.XMLGrammarPool; +import org.apache.xerces.xni.grammars.XSGrammar; +import org.apache.xerces.xs.XSComplexTypeDefinition; +import org.apache.xerces.xs.XSElementDeclaration; +import org.apache.xerces.xs.XSModel; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import java.util.Arrays; +import java.util.Map; +import java.util.Vector; + +/** + * @author Dmitry Avdeev + */ +@SuppressWarnings({"UseOfObsoleteCollectionType"}) +public class XmlConstraintsTest extends CodeInsightFixtureTestCase { + + public void testXercesGrammar() throws Exception { + XSModel xsModel = getXSModel("test.xml", "test.xsd"); + XSElementDeclaration elementDeclaration = xsModel.getElementDeclaration("a", ""); + XSComplexTypeDefinition typeDefinition = (XSComplexTypeDefinition)elementDeclaration.getTypeDefinition(); + CMBuilder cmBuilder = new CMBuilder(new CMNodeFactory()); + XSCMValidator validator = cmBuilder.getContentModel((XSComplexTypeDecl)typeDefinition, true); + int[] ints = validator.startContentModel(); + Vector vector = validator.whatCanGoHere(ints); + XSElementDecl o = (XSElementDecl)vector.get(0); + assertEquals("b", o.getName()); + } + + public void testXercesIncomplete() throws Exception { + XSModel xsModel = getXSModel("testIncomplete.xml", "test.xsd"); + XSElementDeclaration elementDeclaration = xsModel.getElementDeclaration("a", ""); + XSComplexTypeDefinition typeDefinition = (XSComplexTypeDefinition)elementDeclaration.getTypeDefinition(); + CMBuilder cmBuilder = new CMBuilder(new CMNodeFactory()); + XSCMValidator validator = cmBuilder.getContentModel((XSComplexTypeDecl)typeDefinition, true); + int[] ints = validator.startContentModel(); + Vector vector = validator.whatCanGoHere(ints); + XSElementDecl o = (XSElementDecl)vector.get(0); + assertEquals("b", o.getName()); + } + + public void testXercesForCompletion() throws Exception { + XSModel xsModel = getXSModel("testCompletion.xml", "test.xsd"); + PsiElement element = myFixture.getFile().findElementAt(getEditor().getCaretModel().getOffset()); + XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class); + + assert tag != null; + XSElementDeclaration elementDeclaration = xsModel.getElementDeclaration(tag.getLocalName(), tag.getNamespace()); + XSComplexTypeDefinition typeDefinition = (XSComplexTypeDefinition)elementDeclaration.getTypeDefinition(); + CMBuilder cmBuilder = new CMBuilder(new CMNodeFactory()); + XSCMValidator validator = cmBuilder.getContentModel((XSComplexTypeDecl)typeDefinition, true); + int[] ints = validator.startContentModel(); + Vector vector = validator.whatCanGoHere(ints); + XSElementDecl o = (XSElementDecl)vector.get(0); + assertEquals("b", o.getName()); + } + + private XSModel getXSModel(String... files) { + myFixture.configureByFiles(files); + + XmlFile file = (XmlFile)myFixture.getFile(); + ValidateXmlActionHandler handler = new ValidateXmlActionHandler(false) { + @Override + protected SAXParser createParser() throws SAXException, ParserConfigurationException { + SAXParser parser = super.createParser(); + parser.getXMLReader().setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE, true); + return parser; + } + }; + handler.setErrorReporter(handler.new TestErrorReporter()); + handler.doValidate(file); + XMLGrammarPool grammarPool = ValidateXmlActionHandler.getGrammarPool(file); + assert grammarPool != null; + Grammar[] grammars = grammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); + XSGrammar grammar = (XSGrammar)grammars[0]; + return grammar.toXSModel(); + } + + public void testXsdConstraints() throws Exception { + Map map = configure("test.xml", "test.xsd"); + XmlElementDescriptor a = map.get("a"); + XmlElementsGroup topGroup = a.getTopGroup(); + } + + public void testDtdConstraints() throws Exception { + + Map map = configure("testDtd.xml"); + XmlElementDescriptor a = map.get("a"); + XmlElementDescriptor b = map.get("b"); + + XmlElementDescriptor c = map.get("c"); + + XmlElementDescriptor d = map.get("d"); + + XmlElementDescriptor e = map.get("e"); + } + + private Map configure(String... files) { + myFixture.configureByFiles(files); + XmlTag tag = ((XmlFile)getFile()).getRootTag(); + assertNotNull(tag); + XmlElementDescriptor descriptor = tag.getDescriptor(); + assertNotNull(descriptor); + XmlElementDescriptor[] descriptors = descriptor.getElementsDescriptors(tag); + Map map = + ContainerUtil.assignKeys(Arrays.asList(descriptors).iterator(), new Convertor() { + @Override + public String convert(XmlElementDescriptor o) { + return o.getName(); + } + }); + map.put(tag.getName(), tag.getDescriptor()); + return map; + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/constraints"; + } + + @Override + protected boolean isCommunity() { + return true; + } +} diff --git a/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java b/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java new file mode 100644 index 000000000000..a7d27d5a7008 --- /dev/null +++ b/xml/tests/src/com/intellij/xml/XmlNamespacesTest.java @@ -0,0 +1,249 @@ +package com.intellij.xml; + +import com.intellij.codeInsight.actions.OptimizeImportsProcessor; +import com.intellij.codeInsight.daemon.impl.analysis.XmlUnusedNamespaceInspection; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.htmlInspections.XmlInspectionToolProvider; +import com.intellij.javaee.ExternalResourceManagerImpl; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; + +/** + * @author Dmitry Avdeev + */ +public class XmlNamespacesTest extends CodeInsightFixtureTestCase { + + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") + public XmlNamespacesTest() { + IdeaTestCase.initPlatformPrefix(); + } + + public void testUnusedNamespaces() throws Exception { + doUnusedDeclarationTest( + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"/>", + "", XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME); + } + + public void testUnusedDefaultNamespace() throws Exception { + doUnusedDeclarationTest("xmlns=\"http://www.w3.org/2001/XInclude\"\n" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " xsi:noNamespaceSchemaLocation=\"http://www.w3.org/2001/XInclude\">\n" + + "", + + "\n" + + "", XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME, false); + + doOptimizeImportsTest("\n" + + ""); + } + + public void testDifferentPrefixes() throws Exception { + doUnusedDeclarationTest( + "xmlns=\"http://www.w3.org/2001/XMLSchema\"\n" + + " xmlns:x=\"http://www.w3.org/2001/XMLSchema\"\n" + + " xmlns:y=\"http://www.w3.org/2001/XMLSchema\"/>", + + "", + XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME, false); + + doOptimizeImportsTest(""); + } + + public void testUnusedLocation() throws Exception { + doUnusedDeclarationTest("http://www.w3.org/2001/XMLSche " + + "http://www.w3.org/2001/XMLSchema.xsd\"/>", + "", + XmlUnusedNamespaceInspection.RemoveNamespaceLocationFix.NAME); + } + + public void testUnusedLocationOnly() throws Exception { + doUnusedDeclarationTest("xmlns:y=\"http://www.w3.org/2001/XInclude\"\n" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " xsi:schemaLocation=\"http://www.w3.org/2001/XInclude http://www.w3.org/2001/XInclude.xsd\n" + + " http://www.w3.org/2001/XMLSchema http://www.w3.org/2001/XMLSchema.xsd\"/>", + "", + XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME); + } + + public void testUnusedDefaultLocation() throws Exception { + doUnusedDeclarationTest("xsi:noNamespaceSchemaLocation=\"zzz\" />", + "", + XmlUnusedNamespaceInspection.RemoveNamespaceLocationFix.NAME); + } + + public void testKeepFormatting() throws Exception { + doUnusedDeclarationTest("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " elementFormDefault=\"qualified\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + "", + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n" + + " \n" + + "", + XmlUnusedNamespaceInspection.RemoveNamespaceDeclarationFix.NAME); + } + + public void testImplicitPrefixUsage() throws Exception { + myFixture.configureByText("a.xml", "xmlns:x3=\"http://www.w3.org/2001/XMLSchema\" >\n" + + " \n" + + ""); + myFixture.testHighlighting(); + } + + public void testUnusedLocationDetection() throws Exception { + myFixture.configureByFile("web-app_2_5.xsd"); + myFixture.configureByText("a.xml", "xmlns:web=\"http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\"\n" + + " xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee\n" + + " web-app_2_5.xsd\"\n" + + " version=\"2.5\">\n" + + ""); + myFixture.testHighlighting(); + } + + public void testWSDD() throws Exception { + myFixture.configureByText("a.xml", + "\n" + + "\n" + + ""); + myFixture.testHighlighting(); + } + + public void testPrefixesInTagValues() throws Exception { + myFixture.configureByText("a.xml", + "<nodeTypes xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\" xmlns:customns=\"http://customurl\">\n" + + "\n" + + " \n" + + " nt:folder\n" + + " \n" + + "\n" + + "nodeTypes>"); + myFixture.testHighlighting(); + } + + public void testLocallyUsedNamespace() throws Exception { + myFixture.configureByText("a.xml", "\n" + + "\n" + + " a.xml\"/>\n" + + ""); + myFixture.testHighlighting(); + } + + public void testSubDirectory() throws Exception { + myFixture.testHighlighting("moved.xml", "trg/move-def.xsd"); + } + + public void testSuppressedOptimize() throws Exception { + myFixture.configureByFile("web-app_2_5.xsd"); + String text = "\n" + + "\n" + + ""; + myFixture.configureByText("a.xml", text); + + doOptimizeImportsTest(text); + } + + private void doUnusedDeclarationTest(String text, String after, String name) throws Exception { + doUnusedDeclarationTest(text, after, name, true); + } + + private void doUnusedDeclarationTest(String text, String after, String name, boolean testOptimizeImports) throws Exception { + myFixture.configureByText("a.xml", text); + myFixture.testHighlighting(); + IntentionAction action = myFixture.getAvailableIntention(name); + assertNotNull(name + " not found", action); + myFixture.launchAction(action); + myFixture.checkResult(after); + + myFixture.configureByText("a.xml", text); + if (testOptimizeImports) { + doOptimizeImportsTest(after); + } + } + + private void doOptimizeImportsTest(String after) { + myFixture.testHighlighting(); + new WriteCommandAction(getProject(), getFile()) { + @Override + protected void run(Result result) throws Throwable { + new OptimizeImportsProcessor(getProject(), getFile()).runWithoutProgress(); + } + }.execute(); + myFixture.checkResult(after); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + myFixture.enableInspections(new XmlInspectionToolProvider()); + ExternalResourceManagerImpl.registerResourceTemporarily("http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd", + getTestDataPath() + "/web-app_2_5.xsd", getTestRootDisposable()); + ExternalResourceManagerImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/", + getTestDataPath() + "/wsdd.dtd", getTestRootDisposable()); + ExternalResourceManagerImpl.registerResourceTemporarily("http://xml.apache.org/axis/wsdd/providers/java", + getTestDataPath() + "/wsdd_provider_java.xsd", getTestRootDisposable()); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/unusedNs"; + } + + @Override + protected boolean isCommunity() { + return true; + } +} diff --git a/xml/tests/src/com/intellij/xml/XmlSchemaPrefixTest.java b/xml/tests/src/com/intellij/xml/XmlSchemaPrefixTest.java new file mode 100644 index 000000000000..feae6f6f487c --- /dev/null +++ b/xml/tests/src/com/intellij/xml/XmlSchemaPrefixTest.java @@ -0,0 +1,47 @@ +package com.intellij.xml; + +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.testFramework.fixtures.CodeInsightTestUtil; +import com.intellij.xml.refactoring.SchemaPrefixRenameHandler; + +/** + * @author Konstantin Bulenkov + */ +public class XmlSchemaPrefixTest extends CodeInsightFixtureTestCase { + + public void testPrefixUsages() throws Exception { + doFindUsages("usages.xml", 16); + doFindUsages("usages1.xml", 16); + } + + public void testRename() throws Exception {doRename();} + public void testRename1() throws Exception {doRename();} + + public void testRename2() throws Exception {doRename();} + public void testRenameFromClosingTag() throws Exception {doRename();} + + private void doRename() throws Exception { + doRename("xsd"); + } + + private void doRename(String newValue) throws Exception { + final String name = getTestName(true); + CodeInsightTestUtil.doInlineRenameTest(new SchemaPrefixRenameHandler(), name, "xml", newValue, myFixture); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/schemaPrefix"; + } + + @Override + protected boolean isCommunity() { + return true; + } + + protected void doFindUsages(String filename, int usages) { + final int size = myFixture.testFindUsages(filename).size(); + assert size == usages : "Threre should be " + usages + " usages, but found " + size + ". File: " + filename; + } + +} diff --git a/xml/tests/src/com/intellij/xml/XmlSmartCompletionTest.java b/xml/tests/src/com/intellij/xml/XmlSmartCompletionTest.java new file mode 100644 index 000000000000..4a01392b3fb2 --- /dev/null +++ b/xml/tests/src/com/intellij/xml/XmlSmartCompletionTest.java @@ -0,0 +1,118 @@ +package com.intellij.xml; + +import com.intellij.codeInsight.CodeInsightSettings; +import com.intellij.codeInsight.completion.CompletionType; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.javaee.ExternalResourceManagerImpl; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public class XmlSmartCompletionTest extends LightPlatformCodeInsightFixtureTestCase { + + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") + public XmlSmartCompletionTest() { + IdeaTestCase.initPlatformPrefix(); + } + + public void testCompletion() throws Exception { + doTest(new String[]{"testCompletion.xml", "test.xsd"}, "b"); + } + + public void testCompletionNext() throws Exception { + doTest(new String[]{"testCompletionNext.xml", "test.xsd"}, "c"); + } + + public void testCompletion3() throws Exception { + doTest(new String[]{"testCompletion3.xml", "test.xsd"}, "c", "d"); + } + + public void testServlet() throws Exception { + doTest(new String[]{"Servlet.xml"}, "icon", "servlet-name"); + } + + public void testServletName() throws Exception { + + doForText("\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "", + "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + ""); + } + + public void testPrefix() throws Exception { + doForText("\n" + + " \n" + + "", + "\n" + + " "); + } + + private void doForText(String before, String after) { + myFixture.configureByText("a.xml", before); + myFixture.complete(CompletionType.SMART); + myFixture.checkResult(after); + } + + private void doTest(String[] files, String... items) { + myFixture.configureByFiles(files); + LookupElement[] elements; + try { + CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION = false; + elements = myFixture.complete(CompletionType.SMART); + } + finally { + CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION = true; + } + assert elements != null; + List strings = ContainerUtil.map(elements, new Function() { + @Override + public String fun(LookupElement lookupElement) { + return lookupElement.getLookupString(); + } + }); + assertEquals(Arrays.asList(items), strings); + } + + + @Override + public void setUp() throws Exception { + super.setUp(); + ExternalResourceManagerImpl.registerResourceTemporarily("http://java.sun.com/j2ee/dtds/web-app_2_3.dtd", + getTestDataPath() + "/web-app_2_3.dtd", getTestRootDisposable()); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/smartCompletion"; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + getBasePath(); + } + +} diff --git a/xml/tests/src/com/intellij/xml/actions/GenerateXmlTagTest.java b/xml/tests/src/com/intellij/xml/actions/GenerateXmlTagTest.java new file mode 100644 index 000000000000..fca9d694ed39 --- /dev/null +++ b/xml/tests/src/com/intellij/xml/actions/GenerateXmlTagTest.java @@ -0,0 +1,84 @@ +package com.intellij.xml.actions; + +import com.intellij.javaee.ExternalResourceManagerImpl; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.fixtures.CodeInsightTestUtil; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; + +import java.io.File; + +/** + * @author Dmitry Avdeev + */ +public class GenerateXmlTagTest extends LightPlatformCodeInsightFixtureTestCase { + + public GenerateXmlTagTest() { + IdeaTestCase.initPlatformPrefix(); + } + + public void testGenerate() throws Exception { + myFixture.configureByFile("web-app_2_5.xsd"); + doTest("generate.xml", "security-constraint"); + } + + public void testGenerateEmpty() throws Exception { + myFixture.configureByFile("javaee_5.xsd"); + myFixture.configureByFile("web-app_2_5.xsd"); + doTest("generateEmpty.xml", "distributable"); + } + + public void testGenerateDTD() throws Exception { + doTest("generateDTD.xml", "b"); + } + + public void testGenerateDTDComplex() throws Exception { + doTest("generateDTDComplex.xml", "b"); + } + + public void testSpring() throws Exception { + myFixture.configureByFile("spring-beans_3.0.xsd"); + doTest("spring.xml", "bean"); + } + + public void testSpringAtCaret() throws Exception { + myFixture.configureByFile("spring-beans_3.0.xsd"); + doTest("springAtCaret.xml", "bean"); + } + + public void testSpringAfterBean() throws Exception { + myFixture.configureByFile("spring-beans_3.0.xsd"); + doTest("springAfterBean.xml", "bean"); + } + + public void testSpringAlias() throws Exception { + myFixture.configureByFile("spring-beans_3.0.xsd"); + doTest("springAlias.xml", "alias"); + } + + public void testInitParam() throws Exception { + doTest("initParam.xml", "context-param"); + } + + private void doTest(String file, String tagName) { + GenerateXmlTagAction.TEST_THREAD_LOCAL.set(tagName); + CodeInsightTestUtil.doActionTest(new GenerateXmlTagAction(), file, myFixture); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + ExternalResourceManagerImpl.registerResourceTemporarily("http://java.sun.com/j2ee/dtds/web-app_2_3.dtd", + getTestDataPath() + "/web-app_2_3.dtd", getTestRootDisposable()); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/generateTag"; + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + getBasePath(); + } +} diff --git a/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java b/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java new file mode 100644 index 000000000000..629b088a47df --- /dev/null +++ b/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java @@ -0,0 +1,26 @@ +package com.intellij.xml.actions; + +import com.intellij.codeInsight.daemon.LightIntentionActionTestCase; +import com.intellij.testFramework.PlatformTestUtil; + +/** + * @author spleaner + */ +@SuppressWarnings({"ALL"}) +public class SplitTagActionTest extends LightIntentionActionTestCase { + public void test() throws Exception { doAllTests(); } + + @Override + protected boolean shouldBeAvailableAfterExecution() { + return true; + } + + @Override + protected String getBasePath() { + return ""; + } + + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath() + "/xml/tests/testData/intentions/splitTag"; + } +} \ No newline at end of file diff --git a/xml/tests/src/com/intellij/xml/index/XmlSchemaIndexTest.java b/xml/tests/src/com/intellij/xml/index/XmlSchemaIndexTest.java new file mode 100644 index 000000000000..abb7f4bdfd57 --- /dev/null +++ b/xml/tests/src/com/intellij/xml/index/XmlSchemaIndexTest.java @@ -0,0 +1,91 @@ +package com.intellij.xml.index; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * @author Dmitry Avdeev + */ +public class XmlSchemaIndexTest extends CodeInsightFixtureTestCase { + + @SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors") + public XmlSchemaIndexTest() { + IdeaTestCase.initPlatformPrefix(); + } + + public void testBuilder() throws IOException { + + VirtualFile file = myFixture.copyFileToProject("spring-beans-2.0.xsd"); + assert file != null; + final Collection tags = XsdTagNameBuilder.computeTagNames(file.getInputStream()); + assert tags != null; + assertEquals(22, tags.size()); + + final String ns = XsdNamespaceBuilder.computeNamespace(file.getInputStream()); + assertEquals("http://www.springframework.org/schema/beans", ns); + + final VirtualFile xsd = myFixture.copyFileToProject("XMLSchema.xsd"); + assert xsd != null; + final String xsns = XsdNamespaceBuilder.computeNamespace(xsd.getInputStream()); + assertEquals("http://www.w3.org/2001/XMLSchema", xsns); + + final Collection xstags = XsdTagNameBuilder.computeTagNames(xsd.getInputStream()); + assert xstags != null; + assertEquals(69, xstags.size()); + assertTrue(xstags.contains("schema")); + } + + public void testTagNameIndex() { + + myFixture.copyDirectoryToProject("", ""); + + final Project project = getProject(); + final Collection tags = XmlTagNamesIndex.getAllTagNames(project); + assertTrue(tags.size() > 26); + final Collection files = XmlTagNamesIndex.getFilesByTagName("bean", project); + assertEquals(1, files.size()); + + final Collection files1 = XmlTagNamesIndex.getFilesByTagName("schema", project); + assertEquals(files1.toString(), 2, files1.size()); + + Collection names = ContainerUtil.map(files1, new Function() { + @Override + public String fun(VirtualFile virtualFile) { + return virtualFile.getName(); + } + }); + List expected = Arrays.asList("XMLSchema.xsd", "XMLSchema.xsd"); + names.removeAll(expected); + assertTrue(files1.toString(), names.isEmpty()); + } + + public void testNamespaceIndex() { + + myFixture.copyDirectoryToProject("", ""); + + final List> files = + XmlNamespaceIndex.getResourcesByNamespace("http://www.springframework.org/schema/beans", + getProject(), + myModule); + assertEquals(1, files.size()); + } + + @Override + protected String getBasePath() { + return "/xml/tests/testData/index"; + } + + @Override + protected boolean isCommunity() { + return true; + } +} diff --git a/xml/tests/testData/commentInjection/broken_syntax.html b/xml/tests/testData/commentInjection/broken_syntax.html new file mode 100644 index 000000000000..d13549dda5ce --- /dev/null +++ b/xml/tests/testData/commentInjection/broken_syntax.html @@ -0,0 +1,14 @@ + + + + title + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjection/broken_syntax.xhtml b/xml/tests/testData/commentInjection/broken_syntax.xhtml new file mode 100644 index 000000000000..f37fe59ae6bb --- /dev/null +++ b/xml/tests/testData/commentInjection/broken_syntax.xhtml @@ -0,0 +1,15 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjection/broken_syntax2.html b/xml/tests/testData/commentInjection/broken_syntax2.html new file mode 100644 index 000000000000..b164bded4475 --- /dev/null +++ b/xml/tests/testData/commentInjection/broken_syntax2.html @@ -0,0 +1,14 @@ + + + + title + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjection/broken_syntax2.xhtml b/xml/tests/testData/commentInjection/broken_syntax2.xhtml new file mode 100644 index 000000000000..9154f2cd2e62 --- /dev/null +++ b/xml/tests/testData/commentInjection/broken_syntax2.xhtml @@ -0,0 +1,15 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjection/complete.html b/xml/tests/testData/commentInjection/complete.html new file mode 100644 index 000000000000..0b7c20cd1947 --- /dev/null +++ b/xml/tests/testData/commentInjection/complete.html @@ -0,0 +1,13 @@ + + + + title + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjection/complete.xhtml b/xml/tests/testData/commentInjection/complete.xhtml new file mode 100644 index 000000000000..a570e87dbd37 --- /dev/null +++ b/xml/tests/testData/commentInjection/complete.xhtml @@ -0,0 +1,15 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjection/complete_after.html b/xml/tests/testData/commentInjection/complete_after.html new file mode 100644 index 000000000000..e8ee0bfcb8bf --- /dev/null +++ b/xml/tests/testData/commentInjection/complete_after.html @@ -0,0 +1,13 @@ + + + + title + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjection/complete_after.xhtml b/xml/tests/testData/commentInjection/complete_after.xhtml new file mode 100644 index 000000000000..5577d12d196b --- /dev/null +++ b/xml/tests/testData/commentInjection/complete_after.xhtml @@ -0,0 +1,15 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjection/injected1.html b/xml/tests/testData/commentInjection/injected1.html new file mode 100644 index 000000000000..c7281d9f69ff --- /dev/null +++ b/xml/tests/testData/commentInjection/injected1.html @@ -0,0 +1,14 @@ + + + + title + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjection/injected1.xhtml b/xml/tests/testData/commentInjection/injected1.xhtml new file mode 100644 index 000000000000..78748c7ec712 --- /dev/null +++ b/xml/tests/testData/commentInjection/injected1.xhtml @@ -0,0 +1,16 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjection/injected2.html b/xml/tests/testData/commentInjection/injected2.html new file mode 100644 index 000000000000..f43a71f11f7d --- /dev/null +++ b/xml/tests/testData/commentInjection/injected2.html @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjectionFormatting/formatting1.html b/xml/tests/testData/commentInjectionFormatting/formatting1.html new file mode 100644 index 000000000000..ed2850eecec2 --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/formatting1.html @@ -0,0 +1,18 @@ + + + +title + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjectionFormatting/formatting1_after.html b/xml/tests/testData/commentInjectionFormatting/formatting1_after.html new file mode 100644 index 000000000000..53c4a712ae18 --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/formatting1_after.html @@ -0,0 +1,18 @@ + + + + title + + + + + \ No newline at end of file diff --git a/xml/tests/testData/commentInjectionFormatting/formatting2.html b/xml/tests/testData/commentInjectionFormatting/formatting2.html new file mode 100644 index 000000000000..5487ba9dff53 --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/formatting2.html @@ -0,0 +1,36 @@ + + + +title + + + + + diff --git a/xml/tests/testData/commentInjectionFormatting/formatting2_after.html b/xml/tests/testData/commentInjectionFormatting/formatting2_after.html new file mode 100644 index 000000000000..d74a7b1fd0af --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/formatting2_after.html @@ -0,0 +1,36 @@ + + + + title + + + + + diff --git a/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1.xhtml b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1.xhtml new file mode 100644 index 000000000000..2b8603650a4f --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1.xhtml @@ -0,0 +1,21 @@ + + + + +title + + + + + + diff --git a/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1_after.xhtml b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1_after.xhtml new file mode 100644 index 000000000000..6d961243af5b --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting1_after.xhtml @@ -0,0 +1,21 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2.xhtml b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2.xhtml new file mode 100644 index 000000000000..21b38f34a783 --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2.xhtml @@ -0,0 +1,39 @@ + + + + +title + + + + + + diff --git a/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2_after.xhtml b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2_after.xhtml new file mode 100644 index 000000000000..d0d7ecb8e4d7 --- /dev/null +++ b/xml/tests/testData/commentInjectionFormatting/xhtmlFormatting2_after.xhtml @@ -0,0 +1,39 @@ + + + + + title + + + + + + diff --git a/xml/tests/testData/constraints/test.xml b/xml/tests/testData/constraints/test.xml new file mode 100644 index 000000000000..624fb3646d02 --- /dev/null +++ b/xml/tests/testData/constraints/test.xml @@ -0,0 +1,3 @@ + + + diff --git a/xml/tests/testData/constraints/test.xsd b/xml/tests/testData/constraints/test.xsd new file mode 100644 index 000000000000..64a520eb0103 --- /dev/null +++ b/xml/tests/testData/constraints/test.xsd @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/xml/tests/testData/constraints/testCompletion.xml b/xml/tests/testData/constraints/testCompletion.xml new file mode 100644 index 000000000000..7345f6a1fc2e --- /dev/null +++ b/xml/tests/testData/constraints/testCompletion.xml @@ -0,0 +1,4 @@ + + + < + diff --git a/xml/tests/testData/constraints/testDtd.xml b/xml/tests/testData/constraints/testDtd.xml new file mode 100644 index 000000000000..4d8c5e68aa7b --- /dev/null +++ b/xml/tests/testData/constraints/testDtd.xml @@ -0,0 +1,10 @@ + + + + + + ]> + + + diff --git a/xml/tests/testData/constraints/testIncomplete.xml b/xml/tests/testData/constraints/testIncomplete.xml new file mode 100644 index 000000000000..007f560105f9 --- /dev/null +++ b/xml/tests/testData/constraints/testIncomplete.xml @@ -0,0 +1,3 @@ + + < + diff --git a/xml/tests/testData/generateTag/generate.xml b/xml/tests/testData/generateTag/generate.xml new file mode 100644 index 000000000000..ba0d537e4aeb --- /dev/null +++ b/xml/tests/testData/generateTag/generate.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/generateDTD.xml b/xml/tests/testData/generateTag/generateDTD.xml new file mode 100644 index 000000000000..d35500a6d389 --- /dev/null +++ b/xml/tests/testData/generateTag/generateDTD.xml @@ -0,0 +1,17 @@ + + + + + + + + ]> + + + + diff --git a/xml/tests/testData/generateTag/generateDTDComplex.xml b/xml/tests/testData/generateTag/generateDTDComplex.xml new file mode 100644 index 000000000000..b35503e1f3b4 --- /dev/null +++ b/xml/tests/testData/generateTag/generateDTDComplex.xml @@ -0,0 +1,19 @@ + + + + + + + + + ]> + + + diff --git a/xml/tests/testData/generateTag/generateDTDComplex_after.xml b/xml/tests/testData/generateTag/generateDTDComplex_after.xml new file mode 100644 index 000000000000..2f2db8a9ba4d --- /dev/null +++ b/xml/tests/testData/generateTag/generateDTDComplex_after.xml @@ -0,0 +1,22 @@ + + + + + + + + + ]> + + + + + + diff --git a/xml/tests/testData/generateTag/generateDTD_after.xml b/xml/tests/testData/generateTag/generateDTD_after.xml new file mode 100644 index 000000000000..f401f5139e87 --- /dev/null +++ b/xml/tests/testData/generateTag/generateDTD_after.xml @@ -0,0 +1,20 @@ + + + + + + + + ]> + + + + + + + diff --git a/xml/tests/testData/generateTag/generateEmpty.xml b/xml/tests/testData/generateTag/generateEmpty.xml new file mode 100644 index 000000000000..ba0d537e4aeb --- /dev/null +++ b/xml/tests/testData/generateTag/generateEmpty.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/generateEmpty_after.xml b/xml/tests/testData/generateTag/generateEmpty_after.xml new file mode 100644 index 000000000000..707c8d3d8abf --- /dev/null +++ b/xml/tests/testData/generateTag/generateEmpty_after.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/generate_after.xml b/xml/tests/testData/generateTag/generate_after.xml new file mode 100644 index 000000000000..58b865b3d270 --- /dev/null +++ b/xml/tests/testData/generateTag/generate_after.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/initParam.xml b/xml/tests/testData/generateTag/initParam.xml new file mode 100644 index 000000000000..ec73f0e4644c --- /dev/null +++ b/xml/tests/testData/generateTag/initParam.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/initParam_after.xml b/xml/tests/testData/generateTag/initParam_after.xml new file mode 100644 index 000000000000..c57f8026f498 --- /dev/null +++ b/xml/tests/testData/generateTag/initParam_after.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/javaee_5.xsd b/xml/tests/testData/generateTag/javaee_5.xsd new file mode 100644 index 000000000000..59b6575b2c3c --- /dev/null +++ b/xml/tests/testData/generateTag/javaee_5.xsd @@ -0,0 +1,2117 @@ + + + + + + + + @(#)javaee_5.xsds 1.63 06/02/07 + + + + + + + Copyright 2003-2005 Sun Microsystems, Inc. + 4150 Network Circle + Santa Clara, California 95054 + U.S.A + All rights reserved. + + Sun Microsystems, Inc. has intellectual property rights + relating to technology described in this document. In + particular, and without limitation, these intellectual + property rights may include one or more of the U.S. patents + listed at http://www.sun.com/patents and one or more + additional patents or pending patent applications in the + U.S. and other countries. + + This document and the technology which it describes are + distributed under licenses restricting their use, copying, + distribution, and decompilation. No part of this document + may be reproduced in any form by any means without prior + written authorization of Sun and its licensors, if any. + + Third-party software, including font technology, is + copyrighted and licensed from Sun suppliers. + + Sun, Sun Microsystems, the Sun logo, Solaris, Java, J2EE, + JavaServer Pages, Enterprise JavaBeans and the Java Coffee + Cup logo are trademarks or registered trademarks of Sun + Microsystems, Inc. in the U.S. and other countries. + + Federal Acquisitions: Commercial Software - Government Users + Subject to Standard License Terms and Conditions. + + + + + + + +The following definitions that appear in the common +shareable schema(s) of J2EE deployment descriptors should be +interpreted with respect to the context they are included: + +Deployment Component may indicate one of the following: + j2ee application; + application client; + web application; + enterprise bean; + resource adapter; + +Deployment File may indicate one of the following: + ear file; + war file; + jar file; + rar file; + + + + + + + + + + + + + + + + This group keeps the usage of the contained description related + elements consistent across Java EE deployment descriptors. + + All elements may occur multiple times with different languages, + to support localization of the content. + + + + + + + + + + + + + + + + + The description type is used by a description element to + provide text describing the parent element. The elements + that use this type should include any information that the + Deployment Component's Deployment File file producer wants + to provide to the consumer of the Deployment Component's + Deployment File (i.e., to the Deployer). Typically, the + tools used by such a Deployment File consumer will display + the description when processing the parent element that + contains the description. + + The lang attribute defines the language that the + description is provided in. The default value is "en" (English). + + + + + + + + + + + + + + + + + This type defines a dewey decimal that is used + to describe versions of documents. + + + + + + + + + + + + + + + + Employee Self Service + + + The value of the xml:lang attribute is "en" (English) by default. + + ]]> + + + + + + + + + + + + + + + EmployeeRecord + + ../products/product.jar#ProductEJB + + ]]> + + + + + + + + + + + + + + The ejb-local-refType is used by ejb-local-ref elements for + the declaration of a reference to an enterprise bean's local + home or to the local business interface of a 3.0 bean. + The declaration consists of: + + - an optional description + - the EJB reference name used in the code of the Deployment + Component that's referencing the enterprise bean. + - the optional expected type of the referenced enterprise bean + - the optional expected local interface of the referenced + enterprise bean or the local business interface of the + referenced enterprise bean. + - the optional expected local home interface of the referenced + enterprise bean. Not applicable if this ejb-local-ref refers + to the local business interface of a 3.0 bean. + - optional ejb-link information, used to specify the + referenced enterprise bean + - optional elements to define injection of the named enterprise + bean into a component field or property. + + + + + + + + + + + + + + + + + + + + + + ejb/Payroll + + ]]> + + + + + + + + + + + + + + The ejb-ref-typeType contains the expected type of the + referenced enterprise bean. + + The ejb-ref-type designates a value + that must be one of the following: + + Entity + Session + + + + + + + + + + + + + + + + + + The ejb-refType is used by ejb-ref elements for the + declaration of a reference to an enterprise bean's home or + to the remote business interface of a 3.0 bean. + The declaration consists of: + + - an optional description + - the EJB reference name used in the code of + the Deployment Component that's referencing the enterprise + bean. + - the optional expected type of the referenced enterprise bean + - the optional remote interface of the referenced enterprise bean + or the remote business interface of the referenced enterprise + bean + - the optional expected home interface of the referenced + enterprise bean. Not applicable if this ejb-ref + refers to the remote business interface of a 3.0 bean. + - optional ejb-link information, used to specify the + referenced enterprise bean + - optional elements to define injection of the named enterprise + bean into a component field or property + + + + + + + + + + + + + + + + + + + + + + + This type is used to designate an empty + element when used. + + + + + + + + + + + + java.lang.Boolean + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + The env-entryType is used to declare an application's + environment entry. The declaration consists of an optional + description, the name of the environment entry, a type + (optional if the value is injected, otherwise required), and + an optional value. + + It also includes optional elements to define injection of + the named resource into fields or JavaBeans properties. + + If a value is not specified and injection is requested, + no injection will occur and no entry of the specified name + will be created. This allows an initial value to be + specified in the source code without being incorrectly + changed when no override has been specified. + + If a value is not specified and no injection is requested, + a value must be supplied during deployment. + + This type is used by env-entry elements. + + + + + + + + + + minAmount + + ]]> + + + + + + + + java.lang.Integer + + ]]> + + + + + + + + 100.00 + + ]]> + + + + + + + + + + + + + + + + + The elements that use this type designate the name of a + Java class or interface. The name is in the form of a + "binary name", as defined in the JLS. This is the form + of name used in Class.forName(). Tools that need the + canonical name (the name used in source code) will need + to convert this binary name to the canonical name. + + + + + + + + + + + + + + + This type defines four different values which can designate + boolean values. This includes values yes and no which are + not designated by xsd:boolean + + + + + + + + + + + + + + + + + + + com.aardvark.payroll.PayrollHome + + ]]> + + + + + + + + + + + + + + The icon type contains small-icon and large-icon elements + that specify the file names for small and large GIF, JPEG, + or PNG icon images used to represent the parent element in a + GUI tool. + + The xml:lang attribute defines the language that the + icon file names are provided in. Its value is "en" (English) + by default. + + + + + + + + + employee-service-icon16x16.jpg + + ]]> + + + + + + + employee-service-icon32x32.jpg + + ]]> + + + + + + + + + + + + + + + + + + An injection target specifies a class and a name within + that class into which a resource should be injected. + + The injection target class specifies the fully qualified + class name that is the target of the injection. The + Java EE specifications describe which classes can be an + injection target. + + The injection target name specifies the target within + the specified class. The target is first looked for as a + JavaBeans property name. If not found, the target is + looked for as a field name. + + The specified resource will be injected into the target + during initialization of the class by either calling the + set method for the target property or by setting a value + into the named field. + + + + + + + + + + + + + + + + The java-identifierType defines a Java identifier. + The users of this type should further verify that + the content does not contain Java reserved keywords. + + + + + + + + + + + + + + + + + This is a generic type that designates a Java primitive + type or a fully qualified name of a Java interface/type, + or an array of such types. + + + + + + + + + + + + + + + + + The jndi-nameType type designates a JNDI name in the + Deployment Component's environment and is relative to the + java:comp/env context. A JNDI name must be unique within the + Deployment Component. + + + + + + + + + + + + + + + This group keeps the usage of the contained JNDI environment + reference elements consistent across Java EE deployment descriptors. + + + + + + + + + + + + + + + + + + + + + + + + + The lifecycle-callback type specifies a method on a + class to be called when a lifecycle event occurs. + Note that each class may have only one lifecycle callback + method for any given event and that the method may not + be overloaded. + + If the lifefycle-callback-class element is missing then + the class defining the callback is assumed to be the + component class in scope at the place in the descriptor + in which the callback definition appears. + + + + + + + + + + + + + + + + The listenerType indicates the deployment properties for a web + application listener bean. + + + + + + + + + + + The listener-class element declares a class in the + application must be registered as a web + application listener bean. The value is the fully + qualified classname of the listener class. + + + + + + + + + + + + + + + The local-homeType defines the fully-qualified + name of an enterprise bean's local home interface. + + + + + + + + + + + + + + + The localType defines the fully-qualified name of an + enterprise bean's local interface. + + + + + + + + + + + + + + + The message-destination-linkType is used to link a message + destination reference or message-driven bean to a message + destination. + + The Assembler sets the value to reflect the flow of messages + between producers and consumers in the application. + + The value must be the message-destination-name of a message + destination in the same Deployment File or in another + Deployment File in the same Java EE application unit. + + Alternatively, the value may be composed of a path name + specifying a Deployment File containing the referenced + message destination with the message-destination-name of the + destination appended and separated from the path name by + "#". The path name is relative to the Deployment File + containing Deployment Component that is referencing the + message destination. This allows multiple message + destinations with the same name to be uniquely identified. + + + + + + + + + + + + + + + jms/StockQueue + + javax.jms.Queue + + Consumes + + CorporateStocks + + + + ]]> + + + + + + + + + The message-destination-ref-name element specifies + the name of a message destination reference; its + value is the environment entry name used in + Deployment Component code. The name is a JNDI name + relative to the java:comp/env context and must be + unique within an ejb-jar (for enterprise beans) or a + Deployment File (for others). + + + + + + + + + + + + + + + + + + + + + javax.jms.Queue + + + ]]> + + + + + + + + + + + + + + The message-destination-usageType specifies the use of the + message destination indicated by the reference. The value + indicates whether messages are consumed from the message + destination, produced for the destination, or both. The + Assembler makes use of this information in linking producers + of a destination with its consumers. + + The value of the message-destination-usage element must be + one of the following: + Consumes + Produces + ConsumesProduces + + + + + + + + + + + + + + + + + + + CorporateStocks + + + + ]]> + + + + + + + + + The message-destination-name element specifies a + name for a message destination. This name must be + unique among the names of message destinations + within the Deployment File. + + + + + + + + + + + + + + + + + + + + + + This type is a general type that can be used to declare + parameter/value lists. + + + + + + + + + + + The param-name element contains the name of a + parameter. + + + + + + + + + + The param-value element contains the value of a + parameter. + + + + + + + + + + + + + + + The elements that use this type designate either a relative + path or an absolute path starting with a "/". + + In elements that specify a pathname to a file within the + same Deployment File, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the Deployment File's namespace. Absolute filenames (i.e., + those starting with "/") also specify names in the root of + the Deployment File's namespace. In general, relative names + are preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + + myPersistenceContext + + + + + myPersistenceContext + + PersistenceUnit1 + + Extended + + + ]]> + + + + + + + + + The persistence-context-ref-name element specifies + the name of a persistence context reference; its + value is the environment entry name used in + Deployment Component code. The name is a JNDI name + relative to the java:comp/env context. + + + + + + + + + The Application Assembler(or BeanProvider) may use the + following syntax to avoid the need to rename persistence + units to have unique names within a Java EE application. + + The Application Assembler specifies the pathname of the + root of the persistence.xml file for the referenced + persistence unit and appends the name of the persistence + unit separated from the pathname by #. The pathname is + relative to the referencing application component jar file. + In this manner, multiple persistence units with the same + persistence unit name may be uniquely identified when the + Application Assembler cannot change persistence unit names. + + + + + + + + + + + + Used to specify properties for the container or persistence + provider. Vendor-specific properties may be included in + the set of properties. Properties that are not recognized + by a vendor must be ignored. Entries that make use of the + namespace javax.persistence and its subnamespaces must not + be used for vendor-specific properties. The namespace + javax.persistence is reserved for use by the specification. + + + + + + + + + + + + + + + + + + + The persistence-context-typeType specifies the transactional + nature of a persistence context reference. + + The value of the persistence-context-type element must be + one of the following: + Transactional + Extended + + + + + + + + + + + + + + + + + + myPersistenceUnit + + + + + myPersistenceUnit + + PersistenceUnit1 + + + + ]]> + + + + + + + + + The persistence-unit-ref-name element specifies + the name of a persistence unit reference; its + value is the environment entry name used in + Deployment Component code. The name is a JNDI name + relative to the java:comp/env context. + + + + + + + + + The Application Assembler(or BeanProvider) may use the + following syntax to avoid the need to rename persistence + units to have unique names within a Java EE application. + + The Application Assembler specifies the pathname of the + root of the persistence.xml file for the referenced + persistence unit and appends the name of the persistence + unit separated from the pathname by #. The pathname is + relative to the referencing application component jar file. + In this manner, multiple persistence units with the same + persistence unit name may be uniquely identified when the + Application Assembler cannot change persistence unit names. + + + + + + + + + + + + + + + + + + + Specifies a name/value pair. + + + + + + + + + + + + + + + + + + + com.wombat.empl.EmployeeService + + ]]> + + + + + + + + + + + + + + The res-authType specifies whether the Deployment Component + code signs on programmatically to the resource manager, or + whether the Container will sign on to the resource manager + on behalf of the Deployment Component. In the latter case, + the Container uses information that is supplied by the + Deployer. + + The value must be one of the two following: + + Application + Container + + + + + + + + + + + + + + + + + + The res-sharing-scope type specifies whether connections + obtained through the given resource manager connection + factory reference can be shared. The value, if specified, + must be one of the two following: + + Shareable + Unshareable + + The default value is Shareable. + + + + + + + + + + + + + + + + + + jms/StockQueue + + javax.jms.Queue + + + + ]]> + + + + + + + + + + The resource-env-ref-name element specifies the name + of a resource environment reference; its value is + the environment entry name used in + the Deployment Component code. The name is a JNDI + name relative to the java:comp/env context and must + be unique within a Deployment Component. + + + + + + + + + + The resource-env-ref-type element specifies the type + of a resource environment reference. It is the + fully qualified name of a Java language class or + interface. + + + + + + + + + + + + + + + + + + jdbc/EmployeeAppDB + javax.sql.DataSource + Container + Shareable + + + ]]> + + + + + + + + + + The res-ref-name element specifies the name of a + resource manager connection factory reference. + The name is a JNDI name relative to the + java:comp/env context. + The name must be unique within a Deployment File. + + + + + + + + + + The res-type element specifies the type of the data + source. The type is specified by the fully qualified + Java language class or interface + expected to be implemented by the data source. + + + + + + + + + + + + + + + + + + + + + + This group collects elements that are common to all the + JNDI resource elements. + + + + + + + + + + + + + + + + + + + + + + + The role-nameType designates the name of a security role. + + The name must conform to the lexical rules for a token. + + + + + + + + + + + + + + + + The run-asType specifies the run-as identity to be + used for the execution of a component. It contains an + optional description, and the name of a security role. + + + + + + + + + + + + + + + + + + The security-role-refType contains the declaration of a + security role reference in a component's or a + Deployment Component's code. The declaration consists of an + optional description, the security role name used in the + code, and an optional link to a security role. If the + security role is not specified, the Deployer must choose an + appropriate security role. + + + + + + + + + + + The value of the role-name element must be the String used + as the parameter to the + EJBContext.isCallerInRole(String roleName) method or the + HttpServletRequest.isUserInRole(String role) method. + + + + + + + + + + The role-link element is a reference to a defined + security role. The role-link element must contain + the name of one of the security roles defined in the + security-role elements. + + + + + + + + + + + + + + + + This role includes all employees who are authorized + to access the employee service application. + + employee + + + ]]> + + + + + + + + + + + + + + + + + This is a special string datatype that is defined by Java EE as + a base type for defining collapsed strings. When schemas + require trailing/leading space elimination as well as + collapsing the existing whitespace, this base type may be + used. + + + + + + + + + + + + + + + + + This simple type designates a boolean with only two + permissible values + + - true + - false + + + + + + + + + + + + + + + + + The url-patternType contains the url pattern of the mapping. + It must follow the rules specified in Section 11.2 of the + Servlet API Specification. This pattern is assumed to be in + URL-decoded form and must not contain CR(#xD) or LF(#xA). + If it contains those characters, the container must inform + the developer with a descriptive error message. + The container must preserve all characters including whitespaces. + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:anyURI. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:boolean. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:integer. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:NMTOKEN. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:nonNegativeInteger. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:positiveInteger. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:QName. + + + + + + + + + + + + + + + + + This type adds an "id" attribute to xsd:string. + + + + + + + + + + + + diff --git a/xml/tests/testData/generateTag/spring-beans_3.0.xsd b/xml/tests/testData/generateTag/spring-beans_3.0.xsd new file mode 100644 index 000000000000..0d6b8483de2b --- /dev/null +++ b/xml/tests/testData/generateTag/spring-beans_3.0.xsd @@ -0,0 +1,1162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /' element. + ]]> + + + + + + + + + + /' element. + ]]> + + + + + + + + + + + + + + /' element. + ]]> + + + + + + + + + + + + + ' element for the semantic details of autowire candidate beans. + ]]> + + + + + /' element. + ]]> + + + + + /' element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + element (or "ref" + attribute). We recommend this in most cases as it makes documentation + more explicit. + + 2. "byName" + Autowiring by property name. If a bean of class Cat exposes a dog + property, Spring will try to set this to the value of the bean "dog" + in the current container. If there is no matching bean by name, nothing + special happens; use dependency-check="objects" to raise an error in + that case. + + 3. "byType" + Autowiring if there is exactly one bean of the property type in the + container. If there is more than one, a fatal error is raised, and + you cannot use byType autowiring for that bean. If there is none, + nothing special happens; use dependency-check="objects" to raise an + error in that case. + + 4. "constructor" + Analogous to "byType" for constructor arguments. If there is not exactly + one bean of the constructor argument type in the bean factory, a fatal + error is raised. + + 5. "autodetect" + Chooses "constructor" or "byType" through introspection of the bean + class. If a default constructor is found, "byType" gets applied. + + Note that explicit dependencies, i.e. "property" and "constructor-arg" + elements, always override autowiring. Autowire behavior can be combined + with dependency checking, which will be performed after all autowiring + has been completed. + + Note: This attribute will not be inherited by child bean definitions. + Hence, it needs to be specified per concrete bean definition. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " element. + ]]> + + + + + ..." element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." + element. + ]]> + + + + + ". + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/generateTag/spring.xml b/xml/tests/testData/generateTag/spring.xml new file mode 100644 index 000000000000..d1de923b46c3 --- /dev/null +++ b/xml/tests/testData/generateTag/spring.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAfterBean.xml b/xml/tests/testData/generateTag/springAfterBean.xml new file mode 100644 index 000000000000..060afedb5f53 --- /dev/null +++ b/xml/tests/testData/generateTag/springAfterBean.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAfterBean_after.xml b/xml/tests/testData/generateTag/springAfterBean_after.xml new file mode 100644 index 000000000000..34f3dd701250 --- /dev/null +++ b/xml/tests/testData/generateTag/springAfterBean_after.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAlias.xml b/xml/tests/testData/generateTag/springAlias.xml new file mode 100644 index 000000000000..d1de923b46c3 --- /dev/null +++ b/xml/tests/testData/generateTag/springAlias.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAlias_after.xml b/xml/tests/testData/generateTag/springAlias_after.xml new file mode 100644 index 000000000000..43b11320d9a0 --- /dev/null +++ b/xml/tests/testData/generateTag/springAlias_after.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAtCaret.xml b/xml/tests/testData/generateTag/springAtCaret.xml new file mode 100644 index 000000000000..694aec7797af --- /dev/null +++ b/xml/tests/testData/generateTag/springAtCaret.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/springAtCaret_after.xml b/xml/tests/testData/generateTag/springAtCaret_after.xml new file mode 100644 index 000000000000..35a9c23a2264 --- /dev/null +++ b/xml/tests/testData/generateTag/springAtCaret_after.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/spring_after.xml b/xml/tests/testData/generateTag/spring_after.xml new file mode 100644 index 000000000000..9de096a1a2dc --- /dev/null +++ b/xml/tests/testData/generateTag/spring_after.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/xml/tests/testData/generateTag/web-app_2_3.dtd b/xml/tests/testData/generateTag/web-app_2_3.dtd new file mode 100644 index 000000000000..5e3ab01c0fe8 --- /dev/null +++ b/xml/tests/testData/generateTag/web-app_2_3.dtd @@ -0,0 +1,1063 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/generateTag/web-app_2_5.xsd b/xml/tests/testData/generateTag/web-app_2_5.xsd new file mode 100644 index 000000000000..28e956fd8ccf --- /dev/null +++ b/xml/tests/testData/generateTag/web-app_2_5.xsd @@ -0,0 +1,1290 @@ + + + + + + + + @(#)web-app_2_5.xsds 1.62 05/08/06 + + + + + + + Copyright 2003-2005 Sun Microsystems, Inc. + 4150 Network Circle + Santa Clara, California 95054 + U.S.A + All rights reserved. + + Sun Microsystems, Inc. has intellectual property rights + relating to technology described in this document. In + particular, and without limitation, these intellectual + property rights may include one or more of the U.S. patents + listed at http://www.sun.com/patents and one or more + additional patents or pending patent applications in the + U.S. and other countries. + + This document and the technology which it describes are + distributed under licenses restricting their use, copying, + distribution, and decompilation. No part of this document + may be reproduced in any form by any means without prior + written authorization of Sun and its licensors, if any. + + Third-party software, including font technology, is + copyrighted and licensed from Sun suppliers. + + Sun, Sun Microsystems, the Sun logo, Solaris, Java, J2EE, + JavaServer Pages, Enterprise JavaBeans and the Java Coffee + Cup logo are trademarks or registered trademarks of Sun + Microsystems, Inc. in the U.S. and other countries. + + Federal Acquisitions: Commercial Software - Government Users + Subject to Standard License Terms and Conditions. + + + + + + + + ... + + + The instance documents may indicate the published version of + the schema using the xsi:schemaLocation attribute for Java EE + namespace with the following location: + + http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd + + ]]> + + + + + + + The following conventions apply to all Java EE + deployment descriptor elements unless indicated otherwise. + + - In elements that specify a pathname to a file within the + same JAR file, relative filenames (i.e., those not + starting with "/") are considered relative to the root of + the JAR file's namespace. Absolute filenames (i.e., those + starting with "/") also specify names in the root of the + JAR file's namespace. In general, relative names are + preferred. The exception is .war files where absolute + names are preferred for consistency with the Servlet API. + + + + + + + + + + + + + + + The web-app element is the root of the deployment + descriptor for a web application. Note that the sub-elements + of this element can be in the arbitrary order. Because of + that, the multiplicity of the elements of distributable, + session-config, welcome-file-list, jsp-config, login-config, + and locale-encoding-mapping-list was changed from "?" to "*" + in this schema. However, the deployment descriptor instance + file must not contain multiple elements of session-config, + jsp-config, and login-config. When there are multiple elements of + welcome-file-list or locale-encoding-mapping-list, the container + must concatenate the element contents. The multiple occurence + of the element distributable is redundant and the container + treats that case exactly in the same way when there is only + one distributable. + + + + + + + + + The servlet element contains the name of a servlet. + The name must be unique within the web application. + + + + + + + + + + + + The filter element contains the name of a filter. + The name must be unique within the web application. + + + + + + + + + + + + The ejb-local-ref-name element contains the name of an EJB + reference. The EJB reference is an entry in the web + application's environment and is relative to the + java:comp/env context. The name must be unique within + the web application. + + It is recommended that name is prefixed with "ejb/". + + + + + + + + + + + + The ejb-ref-name element contains the name of an EJB + reference. The EJB reference is an entry in the web + application's environment and is relative to the + java:comp/env context. The name must be unique within + the web application. + + It is recommended that name is prefixed with "ejb/". + + + + + + + + + + + + The resource-env-ref-name element specifies the name of + a resource environment reference; its value is the + environment entry name used in the web application code. + The name is a JNDI name relative to the java:comp/env + context and must be unique within a web application. + + + + + + + + + + + + The message-destination-ref-name element specifies the name of + a message destination reference; its value is the + environment entry name used in the web application code. + The name is a JNDI name relative to the java:comp/env + context and must be unique within a web application. + + + + + + + + + + + + The res-ref-name element specifies the name of a + resource manager connection factory reference. The name + is a JNDI name relative to the java:comp/env context. + The name must be unique within a web application. + + + + + + + + + + + + The env-entry-name element contains the name of a web + application's environment entry. The name is a JNDI + name relative to the java:comp/env context. The name + must be unique within a web application. + + + + + + + + + + + + + A role-name-key is specified to allow the references + from the security-role-refs. + + + + + + + + + + + + The keyref indicates the references from + security-role-ref to a specified role-name. + + + + + + + + + + + + + + + + The auth-constraintType indicates the user roles that + should be permitted access to this resource + collection. The role-name used here must either correspond + to the role-name of one of the security-role elements + defined for this web application, or be the specially + reserved role-name "*" that is a compact syntax for + indicating all roles in the web application. If both "*" + and rolenames appear, the container interprets this as all + roles. If no roles are defined, no user is allowed access + to the portion of the web application described by the + containing security-constraint. The container matches + role names case sensitively when determining access. + + + + + + + + + + + + + + + + + + The auth-methodType is used to configure the authentication + mechanism for the web application. As a prerequisite to + gaining access to any web resources which are protected by + an authorization constraint, a user must have authenticated + using the configured mechanism. Legal values are "BASIC", + "DIGEST", "FORM", "CLIENT-CERT", or a vendor-specific + authentication scheme. + + Used in: login-config + + + + + + + + + + + + + + + + The dispatcher has four legal values: FORWARD, REQUEST, INCLUDE, + and ERROR. A value of FORWARD means the Filter will be applied + under RequestDispatcher.forward() calls. A value of REQUEST + means the Filter will be applied under ordinary client calls to + the path or servlet. A value of INCLUDE means the Filter will be + applied under RequestDispatcher.include() calls. A value of + ERROR means the Filter will be applied under the error page + mechanism. The absence of any dispatcher elements in a + filter-mapping indicates a default of applying filters only under + ordinary client calls to the path or servlet. + + + + + + + + + + + + + + + + + + + + + The encodingType defines IANA character sets. + + + + + + + + + + + + + + + + The error-code contains an HTTP error code, ex: 404 + + Used in: error-page + + + + + + + + + + + + + + + + + + + The error-pageType contains a mapping between an error code + or exception type to the path of a resource in the web + application. + + Used in: web-app + + + + + + + + + + + + + The exception-type contains a fully qualified class + name of a Java exception type. + + + + + + + + + + + The location element contains the location of the + resource in the web application relative to the root of + the web application. The value of the location must have + a leading `/'. + + + + + + + + + + + + + + + Declaration of the filter mappings in this web + application is done by using filter-mappingType. + The container uses the filter-mapping + declarations to decide which filters to apply to a request, + and in what order. The container matches the request URI to + a Servlet in the normal way. To determine which filters to + apply it matches filter-mapping declarations either on + servlet-name, or on url-pattern for each filter-mapping + element, depending on which style is used. The order in + which filters are invoked is the order in which + filter-mapping declarations that match a request URI for a + servlet appear in the list of filter-mapping elements.The + filter-name value must be the value of the filter-name + sub-elements of one of the filter declarations in the + deployment descriptor. + + + + + + + + + + + + + + + + + + + + + + The logical name of the filter is declare + by using filter-nameType. This name is used to map the + filter. Each filter name is unique within the web + application. + + Used in: filter, filter-mapping + + + + + + + + + + + + + + + + The filterType is used to declare a filter in the web + application. The filter is mapped to either a servlet or a + URL pattern in the filter-mapping element, using the + filter-name value to reference. Filters can access the + initialization parameters declared in the deployment + descriptor at runtime via the FilterConfig interface. + + Used in: web-app + + + + + + + + + + + + The fully qualified classname of the filter. + + + + + + + + + + The init-param element contains a name/value pair as + an initialization param of a servlet filter + + + + + + + + + + + + + + + The form-login-configType specifies the login and error + pages that should be used in form based login. If form based + authentication is not used, these elements are ignored. + + Used in: login-config + + + + + + + + + + + The form-login-page element defines the location in the web + app where the page that can be used for login can be + found. The path begins with a leading / and is interpreted + relative to the root of the WAR. + + + + + + + + + + The form-error-page element defines the location in + the web app where the error page that is displayed + when login is not successful can be found. + The path begins with a leading / and is interpreted + relative to the root of the WAR. + + + + + + + + + + + + + + + + + A HTTP method type as defined in HTTP 1.1 section 2.2. + + + + + + + + + + + + + + + + + + + + + + + The locale-encoding-mapping-list contains one or more + locale-encoding-mapping(s). + + + + + + + + + + + + + + + + + The locale-encoding-mapping contains locale name and + encoding name. The locale name must be either "Language-code", + such as "ja", defined by ISO-639 or "Language-code_Country-code", + such as "ja_JP". "Country code" is defined by ISO-3166. + + + + + + + + + + + + + + + + + + The localeType defines valid locale defined by ISO-639-1 + and ISO-3166. + + + + + + + + + + + + + + + + The login-configType is used to configure the authentication + method that should be used, the realm name that should be + used for this application, and the attributes that are + needed by the form login mechanism. + + Used in: web-app + + + + + + + + + + + The realm name element specifies the realm name to + use in HTTP Basic authorization. + + + + + + + + + + + + + + + + The mime-mappingType defines a mapping between an extension + and a mime type. + + Used in: web-app + + + + + + + + + The extension element contains a string describing an + extension. example: "txt" + + + + + + + + + + + + + + + + + The mime-typeType is used to indicate a defined mime type. + + Example: + "text/plain" + + Used in: mime-mapping + + + + + + + + + + + + + + + + + This type defines a string which contains at least one + character. + + + + + + + + + + + + + + + + + + + + + + + + The security-constraintType is used to associate + security constraints with one or more web resource + collections + + Used in: web-app + + + + + + + + + + + + + + + + + + + + The servlet-mappingType defines a mapping between a + servlet and a url pattern. + + Used in: web-app + + + + + + + + + + + + + + + + + + The servlet-name element contains the canonical name of the + servlet. Each servlet name is unique within the web + application. + + + + + + + + + + + + + + + + The servletType is used to declare a servlet. + It contains the declarative data of a + servlet. If a jsp-file is specified and the load-on-startup + element is present, then the JSP should be precompiled and + loaded. + + Used in: web-app + + + + + + + + + + + + + The servlet-class element contains the fully + qualified class name of the servlet. + + + + + + + + + + + + + + + The load-on-startup element indicates that this + servlet should be loaded (instantiated and have + its init() called) on the startup of the web + application. The optional contents of these + element must be an integer indicating the order in + which the servlet should be loaded. If the value + is a negative integer, or the element is not + present, the container is free to load the servlet + whenever it chooses. If the value is a positive + integer or 0, the container must load and + initialize the servlet as the application is + deployed. The container must guarantee that + servlets marked with lower integers are loaded + before servlets marked with higher integers. The + container may choose the order of loading of + servlets with the same load-on-start-up value. + + + + + + + + + + + + + + + + + The session-configType defines the session parameters + for this web application. + + Used in: web-app + + + + + + + + + + The session-timeout element defines the default + session timeout interval for all sessions created + in this web application. The specified timeout + must be expressed in a whole number of minutes. + If the timeout is 0 or less, the container ensures + the default behaviour of sessions is never to time + out. If this element is not specified, the container + must set its default timeout period. + + + + + + + + + + + + + + + The transport-guaranteeType specifies that the communication + between client and server should be NONE, INTEGRAL, or + CONFIDENTIAL. NONE means that the application does not + require any transport guarantees. A value of INTEGRAL means + that the application requires that the data sent between the + client and server be sent in such a way that it can't be + changed in transit. CONFIDENTIAL means that the application + requires that the data be transmitted in a fashion that + prevents other entities from observing the contents of the + transmission. In most cases, the presence of the INTEGRAL or + CONFIDENTIAL flag will indicate that the use of SSL is + required. + + Used in: user-data-constraint + + + + + + + + + + + + + + + + + + + + The user-data-constraintType is used to indicate how + data communicated between the client and container should be + protected. + + Used in: security-constraint + + + + + + + + + + + + + + + + + + The elements that use this type designate a path starting + with a "/" and interpreted relative to the root of a WAR + file. + + + + + + + + + + + + + + + + + This type contains the recognized versions of + web-application supported. It is used to designate the + version of the web application. + + + + + + + + + + + + + + + + + + + + + The context-param element contains the declaration + of a web application's servlet context + initialization parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The metadata-complete attribute defines whether this + deployment descriptor and other related deployment + descriptors for this module (e.g., web service + descriptors) are complete, or whether the class + files available to this module and packaged with + this application should be examined for annotations + that specify deployment information. + + If metadata-complete is set to "true", the deployment + tool must ignore any annotations that specify deployment + information, which might be present in the class files + of the application. + + If metadata-complete is not specified or is set to + "false", the deployment tool must examine the class + files of the application for annotations, as + specified by the specifications. + + + + + + + + + + + + + + The web-resource-collectionType is used to identify a subset + of the resources and HTTP methods on those resources within + a web application to which a security constraint applies. If + no HTTP methods are specified, then the security constraint + applies to all HTTP methods. + + Used in: security-constraint + + + + + + + + + + The web-resource-name contains the name of this web + resource collection. + + + + + + + + + + + + + + + + + + The welcome-file-list contains an ordered list of welcome + files elements. + + Used in: web-app + + + + + + + + + + The welcome-file element contains file name to use + as a default welcome file, such as index.html + + + + + + + + + + diff --git a/xml/tests/testData/generateactions/addColumn/after1.html b/xml/tests/testData/generateactions/addColumn/after1.html new file mode 100644 index 000000000000..d10a2a3e569e --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after1.html @@ -0,0 +1,43 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1233333.333341
121
1231
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after2.xhtml b/xml/tests/testData/generateactions/addColumn/after2.xhtml new file mode 100644 index 000000000000..41226bfed0bc --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after2.xhtml @@ -0,0 +1,41 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1233333.333341
121
1231
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after3.jsp b/xml/tests/testData/generateactions/addColumn/after3.jsp new file mode 100644 index 000000000000..31cfd399289d --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after3.jsp @@ -0,0 +1,74 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12
1252'3
12
1233
14
125
123
1
2324
127345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after4.jspx b/xml/tests/testData/generateactions/addColumn/after4.jspx new file mode 100644 index 000000000000..f491cb9ec5c8 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after4.jspx @@ -0,0 +1,74 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12
1252'3
12
1233
14
125
123
1
2324
127345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after5.html b/xml/tests/testData/generateactions/addColumn/after5.html new file mode 100644 index 000000000000..4f6644ba3152 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after5.html @@ -0,0 +1,79 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12
1252'3
12
1233
14
125
123
1
2324
127345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after6.html b/xml/tests/testData/generateactions/addColumn/after6.html new file mode 100644 index 000000000000..1be42492521f --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after6.html @@ -0,0 +1,11 @@ + + + + + + + + +
1 2 +
1 2 +
1 2
\ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/after7.html b/xml/tests/testData/generateactions/addColumn/after7.html new file mode 100644 index 000000000000..9e19d63ff403 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after7.html @@ -0,0 +1,966 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameValuesInitial valueApplies to
(Default: all)
Inherited?Percentages
(Default: N/A) +
Media groups
'azimuth' +<angle> | [[ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards | inherit +center +  +yes +  +aural + +
'background-attachment' +scroll | fixed | inherit + +scroll +  +no +  +visual + +
'background-color' +<color> | transparent | inherit +transparent +  +no + +  +visual + +
'background-image' +<uri> | none | inherit +none +  +no +  +visual + +
'background-position' +[ [ <percentage> | <length> | left | center | right ] [ <percentage> | <length> | top | center | bottom ]? ] | [ [ left | center | right ] || [ top | center | bottom ] ] | inherit + +0% 0% +  +no +refer to the size of the box itself +visual + +
'background-repeat' +repeat | repeat-x | repeat-y | no-repeat | inherit +repeat +  +no +  +visual + +
'background' +['background-color' || 'background-image' || 'background-repeat' || 'background-attachment' || 'background-position'] | inherit + +see individual properties +  +no +allowed on 'background-position' +visual + +
'border-collapse' +collapse | separate | inherit +separate +'table' and 'inline-table' elements +yes +  +visual + +
'border-color' +[ <color> | transparent ]{1,4} | inherit +see individual properties +  +no +  +visual + +
'border-spacing' + +<length> <length>? | inherit +0 +'table' and 'inline-table' elements  +yes +  +visual + +
'border-style' +<border-style>{1,4} | inherit + +see individual properties +  +no +  +visual + +
'border-top' +'border-right' +'border-bottom' +'border-left' +[ <border-width> || <border-style> || 'border-top-color' ] | inherit + +see individual properties +  +no +  +visual + +
'border-top-color' +'border-right-color' +'border-bottom-color' +'border-left-color' +<color> | transparent | inherit + +the value of the 'color' property +  +no +  +visual + +
'border-top-style' +'border-right-style' +'border-bottom-style' +'border-left-style' +<border-style> | inherit + +none +  +no +  +visual + +
'border-top-width' +'border-right-width' +'border-bottom-width' +'border-left-width' +<border-width> | inherit + +medium +  +no +  +visual + +
'border-width' +<border-width>{1,4} | inherit +see individual properties +  +no +  + +visual + +
'border' +[ <border-width> || <border-style> || 'border-top-color' ] | inherit + +see individual properties +  +no +  +visual + +
'bottom' +<length> | <percentage> | auto | inherit + +auto +positioned elements +no +refer to height of containing block +visual + +
'caption-side' +top | bottom | inherit +top +'table-caption' elements +yes +  +visual + +
'clear' +none | left | right | both | inherit +none +block-level elements +no +  +visual + +
'clip' +<shape> | auto | inherit + +auto +absolutely positioned elements +no +  +visual + +
'color' +<color> | inherit +depends on user agent +  +yes + +  +visual + +
'content' +normal | none | [ <string> | <uri> | <counter> | attr(<identifier>) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit + +normal +:before and :after pseudo-elements +no +  +all + +
'counter-increment' +[ <identifier> <integer>? ]+ | none | inherit +none + +  +no +  +all + +
'counter-reset' +[ <identifier> <integer>? ]+ | none | inherit +none +  + +no +  +all + +
'cue-after' +<uri> | none | inherit +none +  +no +  +aural + +
'cue-before' +<uri> | none | inherit +none +  +no +  +aural + +
'cue' + +[ 'cue-before' || 'cue-after' ] | inherit +see individual properties +  +no +  +aural + +
'cursor' + +[ [<uri> ,]* [ auto | crosshair | default | pointer | move | e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | text | wait | help | progress ] ] | inherit +auto +  +yes +  +visual, interactive + +
'direction' + +ltr | rtl | inherit +ltr +all elements, but see prose +yes +  +visual + +
'display' +inline | block | list-item | run-in | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit +inline +  + +no +  +all + +
'elevation' +<angle> | below | level | above | higher | lower | inherit +level +  +yes +  +aural + +
'empty-cells' +show | hide | inherit +show +'table-cell' elements +yes +  +visual + +
'float' +left | right | none | inherit + +none +all, but see 9.7 +no +  +visual + +
'font-family' +[[ <family-name> | <generic-family> ] [, <family-name>| <generic-family>]* ] | inherit + +depends on user agent +  +yes +  +visual + +
'font-size' +<absolute-size> | <relative-size> | <length> | <percentage> | inherit + +medium +  +yes +refer to parent element's font size +visual + +
'font-style' +normal | italic | oblique | inherit +normal +  +yes +  +visual + +
'font-variant' +normal | small-caps | inherit +normal +  +yes +  +visual + +
'font-weight' +normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit + +normal +  +yes +  +visual + +
'font' +[ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit + +see individual properties +  +yes +see individual properties +visual + +
'height' +<length> | <percentage> | auto | inherit + +auto +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'left' +<length> | <percentage> | auto | inherit + +auto +positioned elements +no +refer to width of containing block +visual + +
'letter-spacing' +normal | <length> | inherit +normal +  + +yes +  +visual + +
'line-height' +normal | <number> | <length> | <percentage> | inherit + +normal +  +yes +refer to the font size of the element itself +visual + +
'list-style-image' +<uri> | none | inherit +none +elements with 'display: list-item' +yes + +  +visual + +
'list-style-position' +inside | outside | inherit +outside +elements with 'display: list-item' +yes +  +visual + +
'list-style-type' + +disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit +disc +elements with 'display: list-item' +yes +  +visual + +
'list-style' +[ 'list-style-type' || 'list-style-position' || 'list-style-image' ] | inherit + +see individual properties +elements with 'display: list-item' +yes +  +visual + +
'margin-right' +'margin-left' +<margin-width> | inherit +0 + +all elements except elements with table display types other than table-caption, table and inline-table +no +refer to width of containing block +visual + +
'margin-top' +'margin-bottom' +<margin-width> | inherit +0 +all elements except elements with table display types other than table-caption, table and inline-table + +no +refer to width of containing block +visual + +
'margin' +<margin-width>{1,4} | inherit +see individual properties +all elements except elements with table display types other than table-caption, table and inline-table +no +refer to width of containing block +visual + +
'max-height' +<length> | <percentage> | none | inherit +none +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'max-width' +<length> | <percentage> | none | inherit +none +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block +visual + +
'min-height' +<length> | <percentage> | inherit +0 +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'min-width' +<length> | <percentage> | inherit +0 +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block +visual + +
'orphans' +<integer> | inherit +2 +block-level elements +yes +  +visual, paged + +
'outline-color' +<color> | invert | inherit +invert +  +no +  +visual, interactive + +
'outline-style' + +<border-style> | inherit +none +  +no +  +visual, interactive + +
'outline-width' +<border-width> | inherit + +medium +  +no +  +visual, interactive + +
'outline' +[ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit + +see individual properties +  +no +  +visual, interactive + +
'overflow' +visible | hidden | scroll | auto | inherit +visible +non-replaced block-level elements, table cells, and inline-block elements +no + +  +visual + +
'padding-top' +'padding-right' +'padding-bottom' +'padding-left' +<padding-width> | inherit + +0 +all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column +no +refer to width of containing block +visual + +
'padding' +<padding-width>{1,4} | inherit +see individual properties +all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column +no +refer to width of containing block + +visual + +
'page-break-after' +auto | always | avoid | left | right | inherit +auto +block-level elements +no +  +visual, paged + +
'page-break-before' +auto | always | avoid | left | right | inherit +auto +block-level elements +no +  +visual, paged + +
'page-break-inside' +avoid | auto | inherit + +auto +block-level elements +yes +  +visual, paged + +
'pause-after' +<time> | <percentage> | inherit + +0 +  +no +see prose +aural + +
'pause-before' +<time> | <percentage> | inherit + +0 +  +no +see prose +aural + +
'pause' +[ [<time> | <percentage>]{1,2} ] | inherit + +see individual properties +  +no +see descriptions of 'pause-before' and 'pause-after' +aural + +
'pitch-range' +<number> | inherit +50 +  +yes + +  +aural + +
'pitch' +<frequency> | x-low | low | medium | high | x-high | inherit +medium +  +yes +  +aural + +
'play-during' +<uri> [ mix || repeat ]? | auto | none | inherit +auto +  +no +  +aural + +
'position' + +static | relative | absolute | fixed | inherit +static +  +no +  +visual + +
'quotes' +[<string> <string>]+ | none | inherit + +depends on user agent +  +yes +  +visual + +
'richness' +<number> | inherit +50 +  +yes + +  + aural + +
'right' +<length> | <percentage> | auto | inherit +auto +positioned elements +no + +refer to width of containing block + visual + +
'speak-header' +once | always | inherit +once +elements that have table header information +yes +  + aural + +
'speak-numeral' + +digits | continuous | inherit +continuous +  +yes +  + aural + +
'speak-punctuation' +code | none | inherit +none +  + +yes +  + aural + +
'speak' +normal | none | spell-out | inherit +normal +  +yes +  + aural + +
'speech-rate' +<number> | x-slow | slow | medium | fast | x-fast | faster | slower | inherit +medium +  +yes +  + aural + +
'stress' +<number> | inherit + +50 +  +yes +  + aural + +
'table-layout' +auto | fixed | inherit +auto +'table' and 'inline-table' elements +no +  + visual + +
'text-align' +left | right | center | justify | inherit +a nameless value that acts as 'left' if 'direction' is 'ltr', 'right' if 'direction' is 'rtl' +block-level elements, table cells and inline blocks +yes +  + visual + +
'text-decoration' +none | [ underline || overline || line-through || blink ] | inherit + +none +  +no (see prose) +  + visual + +
'text-indent' +<length> | <percentage> | inherit + +0 +block-level elements, table cells and inline blocks +yes +refer to width of containing block + visual + +
'text-transform' +capitalize | uppercase | lowercase | none | inherit +none +  +yes +  + visual + +
'top' +<length> | <percentage> | auto | inherit +auto +positioned elements +no +refer to height of containing block + visual + +
'unicode-bidi' +normal | embed | bidi-override | inherit +normal +all elements, but see prose +no +  + visual + +
'vertical-align' +baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit + +baseline +inline-level and 'table-cell' elements +no +refer to the 'line-height' of the element itself + visual + +
'visibility' +visible | hidden | collapse | inherit +visible +  +yes +  + visual + +
'voice-family' +[[<specific-voice> | <generic-voice> ],]* [<specific-voice> | <generic-voice> ] | inherit + +depends on user agent +  +yes +  + aural + +
'volume' +<number> | <percentage> | silent | x-soft | soft | medium | loud | x-loud | inherit + +medium +  +yes +refer to inherited value + aural + +
'white-space' +normal | pre | nowrap | pre-wrap | pre-line | inherit +normal +  +yes +  + visual + +
'widows' +<integer> | inherit +2 +block-level elements +yes +  + visual, paged + +
'width' +<length> | <percentage> | auto | inherit +auto +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block + visual + +
'word-spacing' +normal | <length> | inherit +normal +  +yes +  + visual + +
'z-index' + +auto | <integer> | inherit +auto +positioned elements +no +  + visual + +
diff --git a/xml/tests/testData/generateactions/addColumn/after8.xml b/xml/tests/testData/generateactions/addColumn/after8.xml new file mode 100644 index 000000000000..1b4b1a7d970c --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/after8.xml @@ -0,0 +1,41 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + d>3 + + + + + + + + + + + + + + +
1233333.33341
121
1231
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before1.html b/xml/tests/testData/generateactions/addColumn/before1.html new file mode 100644 index 000000000000..1b4b1a7d970c --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before1.html @@ -0,0 +1,41 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + d>3 + + + + + + + + + + + + + + +
1233333.33341
121
1231
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before2.xhtml b/xml/tests/testData/generateactions/addColumn/before2.xhtml new file mode 100644 index 000000000000..c2545b19f3d0 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before2.xhtml @@ -0,0 +1,41 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + d colspan="11">1 + +
1233333.333341
121
123
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before3.jsp b/xml/tests/testData/generateactions/addColumn/before3.jsp new file mode 100644 index 000000000000..f4e9cd48e072 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before3.jsp @@ -0,0 +1,69 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
12
1252'3
12
1233
14
125
123
1
2324
127345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before4.jspx b/xml/tests/testData/generateactions/addColumn/before4.jspx new file mode 100644 index 000000000000..d5d6fe721c0a --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before4.jspx @@ -0,0 +1,69 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d colspan="3" rowspan="3">1 + + + + + + + + + + + + + + + + + + + + + +
12
1252'3
12
1233
14
125
23
1
2324
127345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before5.html b/xml/tests/testData/generateactions/addColumn/before5.html new file mode 100644 index 000000000000..02024f534af6 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before5.html @@ -0,0 +1,69 @@ + + + + + fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d>1 + + + + + + +
12
1252'3
12
1233
14
125
123
1
2324
27345
+ + \ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before6.html b/xml/tests/testData/generateactions/addColumn/before6.html new file mode 100644 index 000000000000..f1826d6ae995 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before6.html @@ -0,0 +1,6 @@ + + + + +
1 h>2 +
1 2
1 2
\ No newline at end of file diff --git a/xml/tests/testData/generateactions/addColumn/before7.html b/xml/tests/testData/generateactions/addColumn/before7.html new file mode 100644 index 000000000000..77015e0eb175 --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before7.html @@ -0,0 +1,866 @@ + + + + +
NameValuesInitial valueApplies to
(Default: all)
Inherited?Percentages
(Default: N/A)
Media groups
'azimuth' +<angle> | [[ left-side | far-left | left | center-left | center | center-right | right | far-right | right-side ] || behind ] | leftwards | rightwards | inherit +center +  +yes +  +aural + +
'background-attachment' +scroll | fixed | inherit + +scroll +  +no +d>  +visual + +
'background-color' +<color> | transparent | inherit +transparent +  +no + +  +visual + +
'background-image' +<uri> | none | inherit +none +  +no +  +visual + +
'background-position' +[ [ <percentage> | <length> | left | center | right ] [ <percentage> | <length> | top | center | bottom ]? ] | [ [ left | center | right ] || [ top | center | bottom ] ] | inherit + +0% 0% +  +no +refer to the size of the box itself +visual + +
'background-repeat' +repeat | repeat-x | repeat-y | no-repeat | inherit +repeat +  +no +  +visual + +
'background' +['background-color' || 'background-image' || 'background-repeat' || 'background-attachment' || 'background-position'] | inherit + +see individual properties +  +no +allowed on 'background-position' +visual + +
'border-collapse' +collapse | separate | inherit +separate +'table' and 'inline-table' elements +yes +  +visual + +
'border-color' +[ <color> | transparent ]{1,4} | inherit +see individual properties +  +no +  +visual + +
'border-spacing' + +<length> <length>? | inherit +0 +'table' and 'inline-table' elements  +yes +  +visual + +
'border-style' +<border-style>{1,4} | inherit + +see individual properties +  +no +  +visual + +
'border-top' +'border-right' +'border-bottom' +'border-left' +[ <border-width> || <border-style> || 'border-top-color' ] | inherit + +see individual properties +  +no +  +visual + +
'border-top-color' +'border-right-color' +'border-bottom-color' +'border-left-color' +<color> | transparent | inherit + +the value of the 'color' property +  +no +  +visual + +
'border-top-style' +'border-right-style' +'border-bottom-style' +'border-left-style' +<border-style> | inherit + +none +  +no +  +visual + +
'border-top-width' +'border-right-width' +'border-bottom-width' +'border-left-width' +<border-width> | inherit + +medium +  +no +  +visual + +
'border-width' +<border-width>{1,4} | inherit +see individual properties +  +no +  + +visual + +
'border' +[ <border-width> || <border-style> || 'border-top-color' ] | inherit + +see individual properties +  +no +  +visual + +
'bottom' +<length> | <percentage> | auto | inherit + +auto +positioned elements +no +refer to height of containing block +visual + +
'caption-side' +top | bottom | inherit +top +'table-caption' elements +yes +  +visual + +
'clear' +none | left | right | both | inherit +none +block-level elements +no +  +visual + +
'clip' +<shape> | auto | inherit + +auto +absolutely positioned elements +no +  +visual + +
'color' +<color> | inherit +depends on user agent +  +yes + +  +visual + +
'content' +normal | none | [ <string> | <uri> | <counter> | attr(<identifier>) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit + +normal +:before and :after pseudo-elements +no +  +all + +
'counter-increment' +[ <identifier> <integer>? ]+ | none | inherit +none + +  +no +  +all + +
'counter-reset' +[ <identifier> <integer>? ]+ | none | inherit +none +  + +no +  +all + +
'cue-after' +<uri> | none | inherit +none +  +no +  +aural + +
'cue-before' +<uri> | none | inherit +none +  +no +  +aural + +
'cue' + +[ 'cue-before' || 'cue-after' ] | inherit +see individual properties +  +no +  +aural + +
'cursor' + +[ [<uri> ,]* [ auto | crosshair | default | pointer | move | e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | text | wait | help | progress ] ] | inherit +auto +  +yes +  +visual, interactive + +
'direction' + +ltr | rtl | inherit +ltr +all elements, but see prose +yes +  +visual + +
'display' +inline | block | list-item | run-in | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit +inline +  + +no +  +all + +
'elevation' +<angle> | below | level | above | higher | lower | inherit +level +  +yes +  +aural + +
'empty-cells' +show | hide | inherit +show +'table-cell' elements +yes +  +visual + +
'float' +left | right | none | inherit + +none +all, but see 9.7 +no +  +visual + +
'font-family' +[[ <family-name> | <generic-family> ] [, <family-name>| <generic-family>]* ] | inherit + +depends on user agent +  +yes +  +visual + +
'font-size' +<absolute-size> | <relative-size> | <length> | <percentage> | inherit + +medium +  +yes +refer to parent element's font size +visual + +
'font-style' +normal | italic | oblique | inherit +normal +  +yes +  +visual + +
'font-variant' +normal | small-caps | inherit +normal +  +yes +  +visual + +
'font-weight' +normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit + +normal +  +yes +  +visual + +
'font' +[ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit + +see individual properties +  +yes +see individual properties +visual + +
'height' +<length> | <percentage> | auto | inherit + +auto +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'left' +<length> | <percentage> | auto | inherit + +auto +positioned elements +no +refer to width of containing block +visual + +
'letter-spacing' +normal | <length> | inherit +normal +  + +yes +  +visual + +
'line-height' +normal | <number> | <length> | <percentage> | inherit + +normal +  +yes +refer to the font size of the element itself +visual + +
'list-style-image' +<uri> | none | inherit +none +elements with 'display: list-item' +yes + +  +visual + +
'list-style-position' +inside | outside | inherit +outside +elements with 'display: list-item' +yes +  +visual + +
'list-style-type' + +disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit +disc +elements with 'display: list-item' +yes +  +visual + +
'list-style' +[ 'list-style-type' || 'list-style-position' || 'list-style-image' ] | inherit + +see individual properties +elements with 'display: list-item' +yes +  +visual + +
'margin-right' +'margin-left' +<margin-width> | inherit +0 + +all elements except elements with table display types other than table-caption, table and inline-table +no +refer to width of containing block +visual + +
'margin-top' +'margin-bottom' +<margin-width> | inherit +0 +all elements except elements with table display types other than table-caption, table and inline-table + +no +refer to width of containing block +visual + +
'margin' +<margin-width>{1,4} | inherit +see individual properties +all elements except elements with table display types other than table-caption, table and inline-table +no +refer to width of containing block +visual + +
'max-height' +<length> | <percentage> | none | inherit +none +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'max-width' +<length> | <percentage> | none | inherit +none +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block +visual + +
'min-height' +<length> | <percentage> | inherit +0 +all elements but non-replaced inline elements, table columns, and column groups +no +see prose +visual + +
'min-width' +<length> | <percentage> | inherit +0 +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block +visual + +
'orphans' +<integer> | inherit +2 +block-level elements +yes +  +visual, paged + +
'outline-color' +<color> | invert | inherit +invert +  +no +  +visual, interactive + +
'outline-style' + +<border-style> | inherit +none +  +no +  +visual, interactive + +
'outline-width' +<border-width> | inherit + +medium +  +no +  +visual, interactive + +
'outline' +[ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit + +see individual properties +  +no +  +visual, interactive + +
'overflow' +visible | hidden | scroll | auto | inherit +visible +non-replaced block-level elements, table cells, and inline-block elements +no + +  +visual + +
'padding-top' +'padding-right' +'padding-bottom' +'padding-left' +<padding-width> | inherit + +0 +all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column +no +refer to width of containing block +visual + +
'padding' +<padding-width>{1,4} | inherit +see individual properties +all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column +no +refer to width of containing block + +visual + +
'page-break-after' +auto | always | avoid | left | right | inherit +auto +block-level elements +no +  +visual, paged + +
'page-break-before' +auto | always | avoid | left | right | inherit +auto +block-level elements +no +  +visual, paged + +
'page-break-inside' +avoid | auto | inherit + +auto +block-level elements +yes +  +visual, paged + +
'pause-after' +<time> | <percentage> | inherit + +0 +  +no +see prose +aural + +
'pause-before' +<time> | <percentage> | inherit + +0 +  +no +see prose +aural + +
'pause' +[ [<time> | <percentage>]{1,2} ] | inherit + +see individual properties +  +no +see descriptions of 'pause-before' and 'pause-after' +aural + +
'pitch-range' +<number> | inherit +50 +  +yes + +  +aural + +
'pitch' +<frequency> | x-low | low | medium | high | x-high | inherit +medium +  +yes +  +aural + +
'play-during' +<uri> [ mix || repeat ]? | auto | none | inherit +auto +  +no +  +aural + +
'position' + +static | relative | absolute | fixed | inherit +static +  +no +  +visual + +
'quotes' +[<string> <string>]+ | none | inherit + +depends on user agent +  +yes +  +visual + +
'richness' +<number> | inherit +50 +  +yes + +  +aural + +
'right' +<length> | <percentage> | auto | inherit +auto +positioned elements +no + +refer to width of containing block +visual + +
'speak-header' +once | always | inherit +once +elements that have table header information +yes +  +aural + +
'speak-numeral' + +digits | continuous | inherit +continuous +  +yes +  +aural + +
'speak-punctuation' +code | none | inherit +none +  + +yes +  +aural + +
'speak' +normal | none | spell-out | inherit +normal +  +yes +  +aural + +
'speech-rate' +<number> | x-slow | slow | medium | fast | x-fast | faster | slower | inherit +medium +  +yes +  +aural + +
'stress' +<number> | inherit + +50 +  +yes +  +aural + +
'table-layout' +auto | fixed | inherit +auto +'table' and 'inline-table' elements +no +  +visual + +
'text-align' +left | right | center | justify | inherit +a nameless value that acts as 'left' if 'direction' is 'ltr', 'right' if 'direction' is 'rtl' +block-level elements, table cells and inline blocks +yes +  +visual + +
'text-decoration' +none | [ underline || overline || line-through || blink ] | inherit + +none +  +no (see prose) +  +visual + +
'text-indent' +<length> | <percentage> | inherit + +0 +block-level elements, table cells and inline blocks +yes +refer to width of containing block +visual + +
'text-transform' +capitalize | uppercase | lowercase | none | inherit +none +  +yes +  +visual + +
'top' +<length> | <percentage> | auto | inherit +auto +positioned elements +no +refer to height of containing block +visual + +
'unicode-bidi' +normal | embed | bidi-override | inherit +normal +all elements, but see prose +no +  +visual + +
'vertical-align' +baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit + +baseline +inline-level and 'table-cell' elements +no +refer to the 'line-height' of the element itself +visual + +
'visibility' +visible | hidden | collapse | inherit +visible +  +yes +  +visual + +
'voice-family' +[[<specific-voice> | <generic-voice> ],]* [<specific-voice> | <generic-voice> ] | inherit + +depends on user agent +  +yes +  +aural + +
'volume' +<number> | <percentage> | silent | x-soft | soft | medium | loud | x-loud | inherit + +medium +  +yes +refer to inherited value +aural + +
'white-space' +normal | pre | nowrap | pre-wrap | pre-line | inherit +normal +  +yes +  +visual + +
'widows' +<integer> | inherit +2 +block-level elements +yes +  +visual, paged + +
'width' +<length> | <percentage> | auto | inherit +auto +all elements but non-replaced inline elements, table rows, and row groups +no +refer to width of containing block +visual + +
'word-spacing' +normal | <length> | inherit +normal +  +yes +  +visual + +
'z-index' + +auto | <integer> | inherit +auto +positioned elements +no +  +visual + +
diff --git a/xml/tests/testData/generateactions/addColumn/before8.xml b/xml/tests/testData/generateactions/addColumn/before8.xml new file mode 100644 index 000000000000..1b4b1a7d970c --- /dev/null +++ b/xml/tests/testData/generateactions/addColumn/before8.xml @@ -0,0 +1,41 @@ + + + + + +fdgsd + + +
dsfgsdgfdg
+ + + + + + + + + + + + + + d>3 + + + + + + + + + + + + + + +
1233333.33341
121
1231
+ + \ No newline at end of file diff --git a/xml/tests/testData/index/XMLSchema.xsd b/xml/tests/testData/index/XMLSchema.xsd new file mode 100644 index 000000000000..07e8e428b369 --- /dev/null +++ b/xml/tests/testData/index/XMLSchema.xsd @@ -0,0 +1,2468 @@ + + + + + Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp + Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp + + + + + + The schema corresponding to this document is normative, + with respect to the syntactic constraints it expresses in the + XML Schema language. The documentation (within <documentation> elements) + below, is not normative, but rather highlights important aspects of + the W3C Recommendation of which this is a part + + + + + The simpleType element and all of its members are defined + towards the end of this schema document + + + + + + Get access to the xml: attribute groups for xml:lang + as declared on 'schema' and 'documentation' below + + + + + + + + This type is extended by almost all schema types + to allow attributes from other namespaces to be + added to user schemas. + + + + + + + + + + + + + This type is extended by all types which allow annotation + other than <schema> itself + + + + + + + + + + + + + + + + This group is for the + elements which occur freely at the top level of schemas. + All of their types are based on the "annotated" type by extension. + + + + + + + + + + + + + This group is for the + elements which can self-redefine (see <redefine> below). + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction} + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction, list, union} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This branch is short for + <complexContent> + <restriction base="xs:anyType"> + ... + </restriction> + </complexContent> + + + + + + + + + + + + + + + Will be restricted to required or forbidden + + + + + + Not allowed if simpleContent child is chosen. + May be overriden by setting on complexContent child. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + No typeDefParticle group reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {substitution, extension, + restriction} + + + + + + + + + + + + + + + + + + + + + + + + + The element element can be used either + at the top level to define an element-type binding globally, + or within a content model to either reference a globally-defined + element or type or declare an element-type binding locally. + The ref form is not allowed at the top level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and + group references + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for the three kinds of group + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice with min/max is here to + avoid a pblm with the Elt:All/Choice/Seq + Particle derivation constraint + + + + + + + + + + restricted max/min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Only elements allowed inside + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all + + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS + + ##local - - any unqualified non-conflicting WFXML/attribute + + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) + + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the following EBNF: + Selector ::= Path ( '|' Path )* + Path ::= ('.//')? Step ( '/' Step )* + Step ::= '.' | NameTest + NameTest ::= QName | '*' | NCName ':' '*' + child:: is also allowed + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the same EBNF as for selector, + with the following change: + Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) + + + + + + + + + + + + + + + + + + + + + + + + + + + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + A public identifier, per ISO 8879 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + notations for use within XML Schema schemas + + + + + + + + + Not the real urType, but as close an approximation as we can + get in the XML representation + + + + + + + + + + First the built-in primitive datatypes. These definitions are for + information only, the real built-in definitions are magic. + + + + For each built-in datatype in this schema (both primitive and + derived) can be uniquely addressed via a URI constructed + as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype + + For example, to address the int datatype, the URI is: + + http://www.w3.org/2001/XMLSchema#int + + Additionally, each facet definition element can be uniquely + addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the facet + + For example, to address the maxInclusive facet, the URI is: + + http://www.w3.org/2001/XMLSchema#maxInclusive + + Additionally, each facet usage in a built-in datatype definition + can be uniquely addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype, followed + by a period (".") followed by the name of the facet + + For example, to address the usage of the maxInclusive facet in + the definition of int, the URI is: + + http://www.w3.org/2001/XMLSchema#int.maxInclusive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOTATION cannot be used directly in a schema; rather a type + must be derived from it by specifying at least one enumeration + facet whose value is the name of a NOTATION declared in the + schema. + + + + + + + + + + Now the derived primitive types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern specifies the content of section 2.12 of XML 1.0e2 + and RFC 3066 (Revised version of RFC 1766). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 7 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 5 from the XML spec + + + + + + + + + + + + + + + pattern matches production 4 from the Namespaces in XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Can be restricted to required or forbidden + + + + + + + + + + + + + + + + + + Required at the top level + + + + + + + + + + + + + + + + + + + Forbidden when nested + + + + + + + + + + + + + + + + + + + We should use a substitution group for facets, but + that's ruled out because it would allow users to + add their own, which we're not ready for yet. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + base attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + itemType attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + + + memberTypes attribute must be non-empty or there must be + at least one simpleType child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/index/spring-beans-2.0.xsd b/xml/tests/testData/index/spring-beans-2.0.xsd new file mode 100644 index 000000000000..6825d93187b9 --- /dev/null +++ b/xml/tests/testData/index/spring-beans-2.0.xsd @@ -0,0 +1,1076 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /' element. + ]]> + + + + + + + + + + /' element. + ]]> + + + + + + + + + + + + + /' element. + ]]> + + + + + + + + + + + + + + /' element. + ]]> + + + + + /' element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + element (or "ref" + attribute). We recommend this in most cases as it makes documentation + more explicit. + + 2. "byName" + Autowiring by property name. If a bean of class Cat exposes a dog + property, Spring will try to set this to the value of the bean "dog" + in the current container. If there is no matching bean by name, nothing + special happens; use dependency-check="objects" to raise an error in + that case. + + 3. "byType" + Autowiring if there is exactly one bean of the property type in the + container. If there is more than one, a fatal error is raised, and + you cannot use byType autowiring for that bean. If there is none, + nothing special happens; use dependency-check="objects" to raise an + error in that case. + + 4. "constructor" + Analogous to "byType" for constructor arguments. If there is not exactly + one bean of the constructor argument type in the bean factory, a fatal + error is raised. + + 5. "autodetect" + Chooses "constructor" or "byType" through introspection of the bean + class. If a default constructor is found, "byType" gets applied. + + Note that explicit dependencies, i.e. "property" and "constructor-arg" + elements, always override autowiring. Autowire behavior can be combined + with dependency checking, which will be performed after all autowiring + has been completed. + + Note: This attribute will not be inherited by child bean definitions. + Hence, it needs to be specified per concrete bean definition. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + " element. + ]]> + + + + + ..." + element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." + element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ". + ]]> + + + + + ..." + element. + ]]> + + + + + ". + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xml/tests/testData/index/spring-tool-2.0.xsd b/xml/tests/testData/index/spring-tool-2.0.xsd new file mode 100644 index 000000000000..3d278bf64466 --- /dev/null +++ b/xml/tests/testData/index/spring-tool-2.0.xsd @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Indicates that an annotated type exports an application visible component. + + + + + + The type of the exported component. May be null if the type is not known until runtime. + + + + + + + Defines an XPath query that can be executed against the node annotated with this + type to determine the identifier of any exported component. + + + + + + diff --git a/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix.html b/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix.html new file mode 100644 index 000000000000..2e0b258453c3 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix.html @@ -0,0 +1,8 @@ + + + + + +u> + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix1.html b/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix1.html new file mode 100644 index 000000000000..53e33d7c45af --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/SwitchToHtml5QuickFix1.html @@ -0,0 +1,10 @@ + + + + + + +nu> + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/after0.html b/xml/tests/testData/inspections/deprecatedTag/actions/after0.html new file mode 100644 index 000000000000..defb3b1e92e7 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/after0.html @@ -0,0 +1,12 @@ + + + + + 1 + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/after1.html b/xml/tests/testData/inspections/deprecatedTag/actions/after1.html new file mode 100644 index 000000000000..d15db0d63370 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/after1.html @@ -0,0 +1,12 @@ + + + + + 1 + + +a +fdfsdfsd + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/after2.jspx b/xml/tests/testData/inspections/deprecatedTag/actions/after2.jspx new file mode 100644 index 000000000000..8ff510623bdf --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/after2.jspx @@ -0,0 +1,11 @@ + + + + + + + + a + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/after3.jsp b/xml/tests/testData/inspections/deprecatedTag/actions/after3.jsp new file mode 100644 index 000000000000..b7c96f21c199 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/after3.jsp @@ -0,0 +1,33 @@ +<%-- "Replace applet tag with object tag" "true" --%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/before0.html b/xml/tests/testData/inspections/deprecatedTag/actions/before0.html new file mode 100644 index 000000000000..53b4398905de --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/before0.html @@ -0,0 +1,12 @@ + + + + + 1 + + +<s> + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/before1.html b/xml/tests/testData/inspections/deprecatedTag/actions/before1.html new file mode 100644 index 000000000000..cf938ebc91c0 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/before1.html @@ -0,0 +1,12 @@ + + + + + 1 + + +>a +fdfsdfsd + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/before2.jspx b/xml/tests/testData/inspections/deprecatedTag/actions/before2.jspx new file mode 100644 index 000000000000..97d8fa3cb089 --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/before2.jspx @@ -0,0 +1,11 @@ + + + + + + + + face="arial" size="+2" color="red">a + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/actions/before3.jsp b/xml/tests/testData/inspections/deprecatedTag/actions/before3.jsp new file mode 100644 index 000000000000..07025457537c --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/actions/before3.jsp @@ -0,0 +1,2 @@ +<%-- "Replace applet tag with object tag" "true" --%> + code="TDMessage.class" align="baseline" width="550" height="150" id="3D Message"> \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xhtml b/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xhtml new file mode 100644 index 000000000000..cd5efad49e1d --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xhtml @@ -0,0 +1,4 @@ + + +:menu/> + \ No newline at end of file diff --git a/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xml b/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xml new file mode 100644 index 000000000000..c70e99b6150e --- /dev/null +++ b/xml/tests/testData/inspections/deprecatedTag/html_deptag5.xml @@ -0,0 +1,9 @@ + + + + size="+666"/> +

+ bla-bla +

+ +
\ No newline at end of file diff --git a/xml/tests/testData/inspections/formInputWithoutLabel/actions/after1.html b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after1.html new file mode 100644 index 000000000000..f1724178b915 --- /dev/null +++ b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after1.html @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/formInputWithoutLabel/actions/after2.xhtml b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after2.xhtml new file mode 100644 index 000000000000..0afb1c1d3ae0 --- /dev/null +++ b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after2.xhtml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/xml/tests/testData/inspections/formInputWithoutLabel/actions/after3.jsp b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after3.jsp new file mode 100644 index 000000000000..7c52117e7f77 --- /dev/null +++ b/xml/tests/testData/inspections/formInputWithoutLabel/actions/after3.jsp @@ -0,0 +1,11 @@ +<%-- "Create a new label from the text after textarea element" "true" --%> +