From a1f054ff7ad0a8b27d602ab16765490c27f4ea27 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 25 Aug 2015 18:45:13 +0300 Subject: [PATCH 01/90] Paths are normalized, so it should be reflected in UI. --- platform/util/src/com/intellij/util/PathMappingSettings.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/PathMappingSettings.java b/platform/util/src/com/intellij/util/PathMappingSettings.java index d5b9683a136d..00c3f00d5df6 100644 --- a/platform/util/src/com/intellij/util/PathMappingSettings.java +++ b/platform/util/src/com/intellij/util/PathMappingSettings.java @@ -263,11 +263,11 @@ public class PathMappingSettings extends AbstractPathMapper implements Cloneable } public void setLocalRoot(@Nullable String localRoot) { - myLocalRoot = localRoot; + myLocalRoot = normalize(localRoot); } public void setRemoteRoot(@Nullable String remoteRoot) { - myRemoteRoot = remoteRoot; + myRemoteRoot = normalize(remoteRoot); } @NotNull From ac2acc315ae55bd46303ffb8ffbc18a85cbfe6ff Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Tue, 25 Aug 2015 18:53:27 +0300 Subject: [PATCH 02/90] Don't remove the slash if it is the only one. --- platform/util/src/com/intellij/util/PathMappingSettings.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/PathMappingSettings.java b/platform/util/src/com/intellij/util/PathMappingSettings.java index 00c3f00d5df6..7c88128cf6fc 100644 --- a/platform/util/src/com/intellij/util/PathMappingSettings.java +++ b/platform/util/src/com/intellij/util/PathMappingSettings.java @@ -299,7 +299,10 @@ public class PathMappingSettings extends AbstractPathMapper implements Cloneable return isAnyEmpty(myLocalRoot, myRemoteRoot); } - private static String trimSlash(String s) { + private static String trimSlash(@NotNull String s) { + if (s.equals("/")) { + return s; + } return StringUtil.trimEnd(s, "/"); } From ac6c8c60e73c5e9249c4ce90379346012b2cddda Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 25 Aug 2015 18:52:42 +0200 Subject: [PATCH 03/90] more VFS logging for blinking PerforceMoveRenameTest --- .../vfs/newvfs/persistent/PersistentFSImpl.java | 16 ++++++++++++---- .../vfs/newvfs/persistent/RefreshWorker.java | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index da3d889bf7b0..d47bdd808339 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -1027,6 +1027,9 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone } private VirtualFileSystemEntry applyEvent(@NotNull VFileEvent event) { + if (LOG.isDebugEnabled()) { + LOG.debug("Applying " + event); + } try { if (event instanceof VFileCreateEvent) { final VFileCreateEvent createEvent = (VFileCreateEvent)event; @@ -1050,17 +1053,22 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone } else if (event instanceof VFilePropertyChangeEvent) { final VFilePropertyChangeEvent propertyChangeEvent = (VFilePropertyChangeEvent)event; + VirtualFile file = propertyChangeEvent.getFile(); + Object newValue = propertyChangeEvent.getNewValue(); if (VirtualFile.PROP_NAME.equals(propertyChangeEvent.getPropertyName())) { - executeRename(propertyChangeEvent.getFile(), (String)propertyChangeEvent.getNewValue()); + executeRename(file, (String)newValue); } else if (VirtualFile.PROP_WRITABLE.equals(propertyChangeEvent.getPropertyName())) { - executeSetWritable(propertyChangeEvent.getFile(), ((Boolean)propertyChangeEvent.getNewValue()).booleanValue()); + executeSetWritable(file, ((Boolean)newValue).booleanValue()); + if (LOG.isDebugEnabled()) { + LOG.debug("File " + file + " writable=" + file.isWritable()); + } } else if (VirtualFile.PROP_HIDDEN.equals(propertyChangeEvent.getPropertyName())) { - executeSetHidden(propertyChangeEvent.getFile(), ((Boolean)propertyChangeEvent.getNewValue()).booleanValue()); + executeSetHidden(file, ((Boolean)newValue).booleanValue()); } else if (VirtualFile.PROP_SYMLINK_TARGET.equals(propertyChangeEvent.getPropertyName())) { - executeSetTarget(propertyChangeEvent.getFile(), (String)propertyChangeEvent.getNewValue()); + executeSetTarget(file, (String)newValue); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java index aee93ddac025..07fcc562978d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java @@ -147,7 +147,7 @@ public class RefreshWorker { boolean currentWritable = persistence.isWritable(file); boolean upToDateWritable = attributes.isWritable(); if (LOG_ATTRIBUTES.isDebugEnabled()) { - LOG_ATTRIBUTES.debug("file=%s writable vfs=%b persistence=%b real=%b", file, file.isWritable(), currentWritable, upToDateWritable); + LOG_ATTRIBUTES.debug("file=" + file + " writable vfs=" + file.isWritable() + " persistence=" + currentWritable + " real=" + upToDateWritable); } if (currentWritable != upToDateWritable) { scheduleAttributeChange(file, VirtualFile.PROP_WRITABLE, currentWritable, upToDateWritable); From 6075505e194476e98536b53260403bd4c7fb3b77 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Tue, 25 Aug 2015 18:45:29 +0300 Subject: [PATCH 04/90] TreeTraverser: EdgeFilter & guided traversal --- .../util/containers/TreeTraverserTest.java | 80 ++++++- .../containers/FilteredTraverserBase.java | 196 ++++++++++++++---- .../intellij/util/containers/JBIterable.java | 10 +- .../intellij/util/containers/JBIterator.java | 2 +- .../util/containers/TreeTraversal.java | 120 +++++++++-- 5 files changed, 341 insertions(+), 67 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java index fe4baed38dad..48e0a4e0d04b 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java @@ -17,6 +17,7 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; +import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.Functions; import com.intellij.util.PairFunction; @@ -235,6 +236,43 @@ public class TreeTraverserTest extends TestCase { assertEquals(JBIterable.generate(1, INCREMENT).take(37).toList(), numTraverser2(TreeTraversal.PLAIN_BFS).fun(1).toList()); } + // GuidedTraversal ---------------------------------------------- + + @NotNull + private static Function.Mono> initGuide(@NotNull final TreeTraversal traversal) { + return new Function.Mono>() { + @Override + public TreeTraversal.GuidedIt fun(TreeTraversal.GuidedIt it) { + return it.setGuide(new Consumer>() { + @Override + public void consume(TreeTraversal.GuidedIt it) { + if (traversal == TreeTraversal.PRE_ORDER_DFS) { + it.queueNext(it.curChild).result(it.curChild); + } + else if (traversal == TreeTraversal.POST_ORDER_DFS) { + it.queueNext(it.curChild).result(it.curChild == null ? it.curParent : null); + } + else if (traversal == TreeTraversal.PLAIN_BFS) { + it.queueLast(it.curChild).result(it.curChild); + } + } + }); + } + }; + } + + public void testGuidedDfs() { + verifyGuidedTraversal(TreeTraversal.PRE_ORDER_DFS); + verifyGuidedTraversal(TreeTraversal.POST_ORDER_DFS); + verifyGuidedTraversal(TreeTraversal.PLAIN_BFS); + } + + private static void verifyGuidedTraversal(TreeTraversal traversal) { + assertEquals(numTraverser2(TreeTraversal.GUIDED_TRAVERSAL).fun(1).intercept(initGuide(traversal)).toList(), + numTraverser2(traversal).fun(1).toList()); + } + + // FilteredTraverser ---------------------------------------------- @NotNull @@ -259,28 +297,28 @@ public class TreeTraverserTest extends TestCase { public void testSkipExpandedDfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(2, 8, 9, 10, 4), t.withRoot(1).expand(IS_ODD).leavesOnlyDfsTraversal().toList()); + assertEquals(Arrays.asList(2, 8, 9, 10, 4), t.withRoot(1).expand(IS_ODD).leavesDfsTraversal().toList()); } public void testRangeChildrenLeavesDfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesOnlyDfsTraversal().toList()); + assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesDfsTraversal().toList()); } public void testRangeChildrenLeavesBfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesOnlyDfsTraversal().toList()); + assertEquals(Arrays.asList(5, 6, 3, 11, 12, 13), t.withRoot(1).children(Conditions.not(inRange(7, 10))).leavesDfsTraversal().toList()); } public void testSkipExpandedBfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(2, 4, 8, 9, 10), t.withRoot(1).expand(IS_ODD).leavesOnlyBfsTraversal().toList()); + assertEquals(Arrays.asList(2, 4, 8, 9, 10), t.withRoot(1).expand(IS_ODD).leavesBfsTraversal().toList()); } public void testExpandSkipFilterReset() { FilteredTraverser t = filteredTraverser(); assertEquals(Arrays.asList(1, 5, 7, 3, 9, 11, 13), t.withRoot(1).expand(IS_ODD). - withTraversal(TreeTraversal.LEAVES_ONLY_DFS).reset().filter(IS_ODD).toList()); + withTraversal(TreeTraversal.LEAVES_DFS).reset().filter(IS_ODD).toList()); } public void testForceExlcudeReset() { @@ -295,7 +333,7 @@ public class TreeTraverserTest extends TestCase { public void testForceSkipLeavesDfs() { FilteredTraverser t = filteredTraverser(); - assertEquals(Arrays.asList(6, 8, 10, 12), t.withRoot(1).forceExpandAndSkip(IS_ODD).leavesOnlyDfsTraversal().toList()); + assertEquals(Arrays.asList(6, 8, 10, 12), t.withRoot(1).forceExpandAndSkip(IS_ODD).leavesDfsTraversal().toList()); } public void testFilterChildren() { @@ -327,4 +365,34 @@ public class TreeTraverserTest extends TestCase { assertEquals(Arrays.asList(21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1), cursor.backtrace().toList()); } + public void testEdgeFilter() { + FilteredTraverser t = filteredTraverser(); + JBIterable it = t.children(new FilteredTraverserBase.EdgeFilter() { + @Override + public boolean value(Integer integer) { + return (integer / curParent) % 2 == 0; + } + }).withRoot(1).traverse(); + assertEquals(Arrays.asList(1, 2, 5, 8, 10, 4, 11), it.toList()); + assertEquals(Arrays.asList(1, 2, 5, 8, 10, 4, 11), it.toList()); + } + + public void testStatefulChildFilter() { + FilteredTraverser t = filteredTraverser(); + class F extends JBIterable.StatefulFilter { + int count; + boolean value; + F(boolean initialVal) { value = initialVal; } + + public boolean value(Integer integer) { + return count ++ > 0 == value; + } + } + + JBIterable it = t.children(new F(true)).withRoot(1).traverse(); + assertEquals(Arrays.asList(1, 5, 6, 7, 3, 9, 10, 4, 12, 13), it.toList()); + assertEquals(Arrays.asList(1, 5, 6, 7, 3, 9, 10, 4, 12, 13), it.toList()); + assertEquals(it.toList(), t.forceExpandAndSkip(new F(false)).withRoot(1).reset().traverse().toList()); + } + } diff --git a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java index 5e01284c0cd5..86c31037247c 100644 --- a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java +++ b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java @@ -16,6 +16,8 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; +import com.intellij.util.Consumer; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,7 +26,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import static com.intellij.openapi.util.Conditions.*; +import static com.intellij.openapi.util.Conditions.not; public abstract class FilteredTraverserBase> implements Iterable { @@ -62,7 +64,7 @@ public abstract class FilteredTraverserBase leavesOnlyDfsTraversal() { - return traverse(TreeTraversal.LEAVES_ONLY_DFS); + public final JBIterable leavesDfsTraversal() { + return traverse(TreeTraversal.LEAVES_DFS); } @NotNull @@ -96,13 +98,13 @@ public abstract class FilteredTraverserBase leavesOnlyBfsTraversal() { - return traverse(TreeTraversal.LEAVES_ONLY_BFS); + public final JBIterable leavesBfsTraversal() { + return traverse(TreeTraversal.LEAVES_BFS); } @NotNull public Self reset() { - return newInstance(Meta.empty().forceExclude(meta.forceExclude).forceExpandAndSkip(meta.forceExpandAndSkip).withRoots(meta.roots)); + return newInstance(meta.reset()); } @NotNull @@ -162,17 +164,20 @@ public abstract class FilteredTraverserBase children(@NotNull T node) { - if (isAlwaysLeaf(node)) return JBIterable.empty(); - JBIterable children = JBIterable.from(tree.fun(node)); - if (meta.childFilter == TRUE && meta.forceExpandAndSkip == Condition.FALSE) { - return children.filter(not(meta.forceExclude)); + if (isAlwaysLeaf(node)) { + return JBIterable.empty(); + } + else if (meta.childFilter.next == null && meta.forceExpandAndSkip.next == null) { + return JBIterable.from(tree.fun(node)).filter(not(meta.forceExclude.OR())); + } + else { + // traverse subtree to select accepted children + return TreeTraversal.GUIDED_TRAVERSAL.traversal(node, tree).intercept(meta.createChildrenGuide(node)); } - // traverse subtree to select accepted children - return newInstance(meta.forChildren(children)).traverse(); } protected boolean isAlwaysLeaf(@NotNull T node) { - return !meta.expandFilter.value(node); + return !meta.expandFilter.valueAnd(node); } @NotNull @@ -185,24 +190,30 @@ public abstract class FilteredTraverserBase extends JBIterable.StatefulFilter { + protected T curParent; + + } + + @SuppressWarnings("unchecked") protected static class Meta { final Iterable roots; final TreeTraversal traversal; - final Condition expandFilter; - final Condition childFilter; - final Condition resultFilter; + final Cond expandFilter; + final Cond childFilter; + final Cond resultFilter; - final Condition forceExclude; - final Condition forceExpandAndSkip; + final Cond forceExclude; + final Cond forceExpandAndSkip; public Meta(@NotNull Iterable roots, @NotNull TreeTraversal traversal, - @NotNull Condition expandFilter, - @NotNull Condition childFilter, - @NotNull Condition resultFilter, - @NotNull Condition forceExclude, - @NotNull Condition forceExpandAndSkip) { + @NotNull Cond expandFilter, + @NotNull Cond childFilter, + @NotNull Cond resultFilter, + @NotNull Cond forceExclude, + @NotNull Cond forceExpandAndSkip) { this.roots = roots; this.traversal = traversal; this.expandFilter = expandFilter; @@ -212,6 +223,10 @@ public abstract class FilteredTraverserBase reset() { + return new Meta(roots, TreeTraversal.PRE_ORDER_DFS, Cond.TRUE, Cond.TRUE, Cond.TRUE, forceExclude, forceExpandAndSkip); + } + public Meta withRoots(@NotNull Iterable roots) { return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, forceExpandAndSkip); } @@ -221,42 +236,147 @@ public abstract class FilteredTraverserBase expand(@NotNull Condition filter) { - return new Meta(roots, traversal, and2(expandFilter, filter), childFilter, resultFilter, forceExclude, - forceExpandAndSkip); + return new Meta(roots, traversal, expandFilter.append(filter), childFilter, resultFilter, forceExclude, forceExpandAndSkip); } public Meta children(@NotNull Condition filter) { - return new Meta(roots, traversal, expandFilter, and2(childFilter, filter), resultFilter, forceExclude, - forceExpandAndSkip); + return new Meta(roots, traversal, expandFilter, childFilter.append(filter), resultFilter, forceExclude, forceExpandAndSkip); } public Meta filter(@NotNull Condition filter) { - return new Meta(roots, traversal, expandFilter, childFilter, and2(resultFilter, filter), forceExclude, - forceExpandAndSkip); + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter.append(filter), forceExclude, forceExpandAndSkip); } // forceExclude and forceSkip filter is always accumulated public Meta forceExclude(Condition filter) { - return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, or2(forceExclude, filter), - forceExpandAndSkip); + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude.append(filter), forceExpandAndSkip); } public Meta forceExpandAndSkip(Condition filter) { - return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, or2(forceExpandAndSkip, filter)); + return new Meta(roots, traversal, expandFilter, childFilter, resultFilter, forceExclude, forceExpandAndSkip.append(filter)); } - public Meta forChildren(JBIterable children) { - Condition expand = or2(forceExpandAndSkip, not(childFilter)); - return new Meta(children, TreeTraversal.LEAVES_ONLY_DFS, expand, TRUE, not(or2(expand, forceExclude)), FALSE, FALSE); + Function.Mono> createChildrenGuide(final T parent) { + final Condition expand = buildExpandConditionForChildren(parent); + class G implements Consumer>, Function.Mono> { + + @Override + public TreeTraversal.GuidedIt fun(TreeTraversal.GuidedIt it) { + return it.setGuide(this); + } + + @Override + public void consume(TreeTraversal.GuidedIt it) { + doPerformChildrenGuidance(it, expand); + } + } + return new G(); + } + + private void doPerformChildrenGuidance(TreeTraversal.GuidedIt it, Condition expand) { + if (it.curChild == null) return; + if (forceExclude.valueOr(it.curChild)) return; + if (it.curParent == null || expand.value(it.curChild)) { + it.queueNext(it.curChild); + } + else { + it.result(it.curChild); + } + } + + private Condition buildExpandConditionForChildren(T parent) { + // implement: or2(forceExpandAndSkip, not(childFilter)); + // and handle JBIterable.StatefulTransform and EdgeFilter conditions + Cond copy = null; + boolean invert = true; + Cond c = childFilter; + while (c != null) { + Condition impl = JBIterable.Stateful.copy(c.impl); + if (impl != (invert ? Condition.TRUE : Condition.FALSE)) { + copy = new Cond(invert ? not(impl) : impl, copy); + if (impl instanceof EdgeFilter) { + ((EdgeFilter)impl).curParent = parent; + } + } + if (c.next == null) { + c = invert ? forceExpandAndSkip : null; + invert = false; + } + else { + c = c.next; + } + } + return copy == null ? Condition.FALSE : copy.OR(); } private static final Meta EMPTY = new Meta( JBIterable.empty(), TreeTraversal.PRE_ORDER_DFS, - TRUE, TRUE, TRUE, - FALSE, FALSE); + Cond.TRUE, Cond.TRUE, Cond.TRUE, + Cond.FALSE, Cond.FALSE); public static Meta empty() { return (Meta)EMPTY; } + } + + private static class Cond { + final static Cond TRUE = new Cond(Conditions.TRUE, null); + final static Cond FALSE = new Cond(Conditions.FALSE, null); + + final Condition impl; + final Cond next; + + Cond(Condition impl, Cond next) { + this.impl = impl; + this.next = next; + } + + Cond append(Condition impl) { + return new Cond(impl, this); + } + + private boolean valueAnd(T t) { + for (Cond c = this; c != null; c = c.next) { + if (!c.impl.value(t)) return false; + } + return true; + } + + private boolean valueOr(T t) { + for (Cond c = this; c != null; c = c.next) { + if (c.impl.value(t)) return true; + } + return false; + } + + Condition OR() { + return new Condition() { + @Override + public boolean value(T t) { + return valueOr(t); + } + }; + } + + Condition AND() { + return new Condition() { + @Override + public boolean value(T t) { + return valueAnd(t); + } + }; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("Cond{"); + for (Cond c = this; c != null; c = c.next) { + sb.append(JBIterator.toShortString(c.impl)); + if (c.next != null) sb.append(", "); + } + return sb.append("}").toString(); + } + } + } diff --git a/platform/util/src/com/intellij/util/containers/JBIterable.java b/platform/util/src/com/intellij/util/containers/JBIterable.java index 9893805e5bca..aa82ccda6540 100644 --- a/platform/util/src/com/intellij/util/containers/JBIterable.java +++ b/platform/util/src/com/intellij/util/containers/JBIterable.java @@ -58,10 +58,12 @@ import java.util.*; * .toList();} *

*

Anything which can be done using {@code JBIterable} could be done in a different fashion - * (often with {@link Iterables}), however the use of {@code JBIterable} makes many sets of + * (often with {@code Iterables}), however the use of {@code JBIterable} makes many sets of * operations significantly more concise. * * @author Marcin Mikosik + * + * @noinspection unchecked */ public abstract class JBIterable implements Iterable { @@ -270,7 +272,6 @@ public abstract class JBIterable implements Iterable { * @param type the type of elements desired */ public final JBIterable filter(@NotNull Class type) { - //noinspection unchecked return (JBIterable)filter(Conditions.instanceOf(type)); } @@ -371,13 +372,13 @@ public abstract class JBIterable implements Iterable { * The most generic iterator transformation. */ @NotNull - public final JBIterable intercept(@NotNull final Function, Iterator> function) { + public final > JBIterable intercept(@NotNull final Function> function) { if (this == EMPTY) return empty(); final JBIterable thisIterable = this; return new JBIterable() { @Override public Iterator iterator() { - return function.fun(thisIterable.iterator()); + return function.fun((X)thisIterable.iterator()); } }; } @@ -459,7 +460,6 @@ public abstract class JBIterable implements Iterable { return collection; } - @SuppressWarnings("unchecked") public abstract static class Stateful implements Cloneable { @NotNull diff --git a/platform/util/src/com/intellij/util/containers/JBIterator.java b/platform/util/src/com/intellij/util/containers/JBIterator.java index ababafdf6474..0edb914742d1 100644 --- a/platform/util/src/com/intellij/util/containers/JBIterator.java +++ b/platform/util/src/com/intellij/util/containers/JBIterator.java @@ -232,7 +232,7 @@ public abstract class JBIterator implements Iterator { }); } - private static String toShortString(@NotNull Object o) { + static String toShortString(@NotNull Object o) { String fqn = o.getClass().getName(); return StringUtil.replace(o.toString(), fqn, StringUtil.getShortName(fqn, '.')); } diff --git a/platform/util/src/com/intellij/util/containers/TreeTraversal.java b/platform/util/src/com/intellij/util/containers/TreeTraversal.java index 87258b7c75a2..76e7aae5f7e8 100644 --- a/platform/util/src/com/intellij/util/containers/TreeTraversal.java +++ b/platform/util/src/com/intellij/util/containers/TreeTraversal.java @@ -16,6 +16,7 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; +import com.intellij.util.Consumer; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -115,17 +116,36 @@ public abstract class TreeTraversal { public abstract JBIterable backtrace(); } - @NotNull - private static Iterable children(@NotNull T root, @NotNull Function> tree) { - return JBIterable.from(tree.fun(root)); + public static abstract class GuidedIt extends It { + @Nullable + public T curChild, curParent; + @Nullable + public Iterable curChildren; + public boolean curNoChildren; + + public abstract GuidedIt setGuide(Consumer> guide); + + public abstract GuidedIt queueNext(T child); + public abstract GuidedIt queueLast(T child); + public abstract GuidedIt result(T node); + } + @NotNull + public static final TreeTraversal GUIDED_TRAVERSAL = new TreeTraversal("GUIDED_TRAVERSAL") { + @NotNull + @Override + public It createIterator(@NotNull Iterable roots, @NotNull Function> tree) { + return new GuidedItImpl(roots, tree); + } + }; + /** * Returns an iterator over the nodes in a tree structure, using pre-order * traversal. That is, each node's subtrees are traversed after the node itself is returned. * *

No guarantees are made about the behavior of the traversal when nodes change while - * iteration is in progress or when the iterators generated by {@link #children} are advanced. + * iteration is in progress or when the iterators generated by {@code tree} are advanced. */ @NotNull public static final TreeTraversal PRE_ORDER_DFS = new TreeTraversal("PRE_ORDER_DFS") { @@ -141,7 +161,7 @@ public abstract class TreeTraversal { * traversal. That is, each node's subtrees are traversed before the node itself is returned. *

*

No guarantees are made about the behavior of the traversal when nodes change while - * iteration is in progress or when the iterators generated by {@link #children} are advanced. + * iteration is in progress or when the iterators generated by {@code tree} are advanced. */ @NotNull public static final TreeTraversal POST_ORDER_DFS = new TreeTraversal("POST_ORDER_DFS") { @@ -154,7 +174,7 @@ public abstract class TreeTraversal { @NotNull - public static final TreeTraversal LEAVES_ONLY_DFS = new TreeTraversal("LEAVES_ONLY_DFS") { + public static final TreeTraversal LEAVES_DFS = new TreeTraversal("LEAVES_DFS") { @NotNull @Override public It createIterator(@NotNull Iterable roots, @NotNull Function> tree) { @@ -167,7 +187,7 @@ public abstract class TreeTraversal { * traversal. That is, all the nodes of depth 0 are returned, then depth 1, then 2, and so on. *

*

No guarantees are made about the behavior of the traversal when nodes change while - * iteration is in progress or when the iterators generated by {@link #children} are advanced. + * iteration is in progress or when the iterators generated by {@code tree} are advanced. */ @NotNull public static final TreeTraversal PLAIN_BFS = new TreeTraversal("PLAIN_BFS") { @@ -188,7 +208,7 @@ public abstract class TreeTraversal { }; @NotNull - public static final TreeTraversal LEAVES_ONLY_BFS = new TreeTraversal("LEAVES_ONLY_BFS") { + public static final TreeTraversal LEAVES_BFS = new TreeTraversal("LEAVES_BFS") { @NotNull @Override public It createIterator(@NotNull Iterable roots, @NotNull Function> tree) { @@ -198,7 +218,7 @@ public abstract class TreeTraversal { // ----------------------------------------------------------------------------- - // Iterators + // Iterators: DFS // ----------------------------------------------------------------------------- private abstract static class DfsIt extends TracingIt { @@ -303,6 +323,10 @@ public abstract class TreeTraversal { } } + // ----------------------------------------------------------------------------- + // Iterators: BFS + // ----------------------------------------------------------------------------- + private static final class BfsIterator extends It { final Function> tree; @@ -317,7 +341,7 @@ public abstract class TreeTraversal { public T nextImpl() { if (queue.isEmpty()) return stop(); T result = queue.remove(); - for (T t : children(result, tree)) queue.add(t); + JBIterable.from(tree.fun(result)).addAllTo(queue); return result; } } @@ -336,9 +360,10 @@ public abstract class TreeTraversal { public T nextImpl() { while (!queue.isEmpty()) { T result = queue.remove(); - Iterator childrenIt = children(result, tree).iterator(); - if (!childrenIt.hasNext()) return result; - while (childrenIt.hasNext()) queue.add(childrenIt.next()); + Iterable children = tree.fun(result); + Iterator it = children == null ? null: children.iterator(); + if (it == null || !it.hasNext()) return result; + while (it.hasNext()) queue.add(it.next()); } return stop(); } @@ -360,7 +385,7 @@ public abstract class TreeTraversal { public T nextImpl() { if (queue.isEmpty()) return stop(); T result = queue.remove(); - for (T t : children(result, tree)) { + for (T t : JBIterable.from(tree.fun(result))) { if (paths.containsKey(t)) continue; queue.add(t); paths.put(t, result); @@ -395,7 +420,68 @@ public abstract class TreeTraversal { }; } } - + + // ----------------------------------------------------------------------------- + // Misc + // ----------------------------------------------------------------------------- + private static final class GuidedItImpl extends GuidedIt { + final ArrayDeque> stack = new ArrayDeque>(); + final Function> tree; + + Consumer> guide; + T curResult; + + GuidedItImpl(@NotNull Iterable roots, Function> tree) { + this.tree = tree; + stack.addLast(P.create(roots)); + } + + public GuidedIt setGuide(Consumer> guide) { + this.guide = guide; + return this; + } + + public GuidedIt queueNext(T child) { + if (child != null) stack.addLast(P.create(child)); + return this; + } + + public GuidedIt queueLast(T child) { + if (child != null) stack.addFirst(P.create(child)); + return this; + } + + public GuidedIt result(T node) { + curResult = node; + return this; + } + + @Override + public T nextImpl() { + if (guide == null) return stop(); + while (!stack.isEmpty()) { + P top = stack.getLast(); + Iterator it = top.iterator(tree); + boolean hasNext = it.hasNext(); + curResult = null; + if (top.node != null || hasNext) { + curChild = hasNext ? it.next() : null; + curParent = top.node; + curChildren = top.itle; + curNoChildren = top.empty; + guide.consume(this); + } + if (!hasNext) { + stack.removeLast(); + } + if (curResult != null) { + return curResult; + } + } + return stop(); + } + } + private static class P { T node; Iterable itle; @@ -404,8 +490,8 @@ public abstract class TreeTraversal { Iterator iterator(@NotNull Function> tree) { if (it != null) return it; - it = (itle != null ? itle : (itle = children(node, tree))).iterator(); - empty = !it.hasNext(); + it = (itle != null ? itle : JBIterable.from(itle = tree.fun(node))).iterator(); + empty = itle == null || !it.hasNext(); return it; } From 85bea6141bf5d3013b573b37e62905cbaf72924d Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 25 Aug 2015 20:22:01 +0300 Subject: [PATCH 05/90] Cleanup (sane overload; warnings; typos; pointless annotations) --- .../migration/MigrationMapSet.java | 4 +- .../src/SchemeManagerImpl.kt | 2 +- .../testFramework/TemporaryDirectory.kt | 2 +- .../intellij/openapi/util/io/FileUtilRt.java | 1 + .../intellij/openapi/util/io/FileUtil.java | 78 +++++++++---------- .../util/UniqueFileNamesProvider.java | 6 +- .../src/settings/IcsSettings.kt | 17 +++- 7 files changed, 60 insertions(+), 50 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/migration/MigrationMapSet.java b/java/java-impl/src/com/intellij/refactoring/migration/MigrationMapSet.java index da55fd30befa..4c1a640a0e92 100644 --- a/java/java-impl/src/com/intellij/refactoring/migration/MigrationMapSet.java +++ b/java/java-impl/src/com/intellij/refactoring/migration/MigrationMapSet.java @@ -1,6 +1,6 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -239,7 +239,7 @@ public class MigrationMapSet { for(int i = 0; i < myMaps.size(); i++){ MigrationMap map = myMaps.get(i); - filePaths[i] = dir + File.separator + namesProvider.generateUniqueName(FileUtil.sanitizeName(map.getName())) + ".xml"; + filePaths[i] = dir + File.separator + namesProvider.generateUniqueName(FileUtil.sanitizeFileName(map.getName(), false)) + ".xml"; documents[i] = saveMap(map); } diff --git a/platform/configuration-store-impl/src/SchemeManagerImpl.kt b/platform/configuration-store-impl/src/SchemeManagerImpl.kt index 7ec4890f0548..48bc88175a2a 100644 --- a/platform/configuration-store-impl/src/SchemeManagerImpl.kt +++ b/platform/configuration-store-impl/src/SchemeManagerImpl.kt @@ -508,7 +508,7 @@ public class SchemeManagerImpl(private val var fileNameWithoutExtension = currentFileNameWithoutExtension if (fileNameWithoutExtension == null || isRenamed(scheme)) { - fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeName(scheme.getName())) + fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeFileName(scheme.getName(), false)) } val newHash = JDOMUtil.getTreeHash(element!!, true) diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt b/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt index fd18b1aebbfa..816255b1afbf 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt +++ b/platform/testFramework/testSrc/com/intellij/testFramework/TemporaryDirectory.kt @@ -35,7 +35,7 @@ public class TemporaryDirectory : ExternalResource() { private var sanitizedName: String? = null override fun apply(base: Statement, description: Description): Statement { - sanitizedName = FileUtil.sanitizeName(description.getMethodName()) + sanitizedName = FileUtil.sanitizeFileName(description.getMethodName(), false) return super.apply(base, description) } diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java index 3dcb22f7ee52..173c099c118c 100644 --- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java +++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java @@ -797,6 +797,7 @@ public class FileUtilRt { return path.isDirectory() || path.mkdirs(); } + @SuppressWarnings("Duplicates") public static void copy(@NotNull File fromFile, @NotNull File toFile) throws IOException { if (!ensureCanCreateFile(toFile)) { return; diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 367745c2d5d4..d980bf0eac7d 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -46,7 +46,8 @@ public class FileUtil extends FileUtilRt { static { if (!Patches.USE_REFLECTION_TO_ACCESS_JDK7) throw new RuntimeException("Please migrate FileUtilRt to JDK8"); } - @NonNls public static final String ASYNC_DELETE_EXTENSION = ".__del__"; + + public static final String ASYNC_DELETE_EXTENSION = ".__del__"; public static final int REGEX_PATTERN_FLAGS = SystemInfo.isFileSystemCaseSensitive ? 0 : Pattern.CASE_INSENSITIVE; @@ -417,7 +418,7 @@ public class FileUtil extends FileUtilRt { private static File getTempFile(@NotNull String originalFileName, @NotNull String parent) { int randomSuffix = (int)(System.currentTimeMillis() % 1000); for (int i = randomSuffix; ; i++) { - @NonNls String name = "___" + originalFileName + i + ASYNC_DELETE_EXTENSION; + String name = "___" + originalFileName + i + ASYNC_DELETE_EXTENSION; File tempFile = new File(parent, name); if (!tempFile.exists()) return tempFile; } @@ -470,6 +471,7 @@ public class FileUtil extends FileUtilRt { performCopy(fromFile, toFile, false); } + @SuppressWarnings("Duplicates") private static void performCopy(@NotNull File fromFile, @NotNull File toFile, final boolean syncTimestamp) throws IOException { final FileOutputStream fos; try { @@ -619,7 +621,7 @@ public class FileUtil extends FileUtilRt { return FileUtilRt.getNameWithoutExtension(name); } - public static String createSequentFileName(@NotNull File aParentFolder, @NotNull @NonNls String aFilePrefix, @NotNull String aExtension) { + public static String createSequentFileName(@NotNull File aParentFolder, @NotNull String aFilePrefix, @NotNull String aExtension) { return findSequentNonexistentFile(aParentFolder, aFilePrefix, aExtension).getName(); } @@ -635,17 +637,18 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static String toSystemDependentName(@NonNls @NotNull String aFileName) { + public static String toSystemDependentName(@NotNull String aFileName) { return FileUtilRt.toSystemDependentName(aFileName); } @NotNull - public static String toSystemIndependentName(@NonNls @NotNull String aFileName) { + public static String toSystemIndependentName(@NotNull String aFileName) { return FileUtilRt.toSystemIndependentName(aFileName); } - @NotNull - public static String nameToCompare(@NonNls @NotNull String name) { + /** @deprecated to be removed in IDEA 17 */ + @SuppressWarnings({"unused", "StringToUpperCaseOrToLowerCaseWithoutLocale"}) + public static String nameToCompare(@NotNull String name) { return (SystemInfo.isFileSystemCaseSensitive ? name : name.toLowerCase()).replace('\\', '/'); } @@ -1148,7 +1151,7 @@ public class FileUtil extends FileUtilRt { builder.append(ch); } - // handle ant shorthand: mypackage/test/ is interpreted as if it were mypackage/test/** + // handle ant shorthand: my_package/test/ is interpreted as if it were my_package/test/** final boolean isTrailingSlash = builder.length() > 0 && builder.charAt(builder.length() - 1) == '/'; if (asteriskCount == 0 && isTrailingSlash || recursive && asteriskCount == 2) { if (isTrailingSlash) { @@ -1185,26 +1188,21 @@ public class FileUtil extends FileUtilRt { return success; } - /** - * Has duplicate: {@link com.intellij.coverage.listeners.CoverageListener#sanitize(java.lang.String, java.lang.String)} - * as FileUtil is not available in client's vm - */ @NotNull public static String sanitizeFileName(@NotNull String name) { return sanitizeFileName(name, true); } - /** - * Difference - not only letter or digit allowed, but space, @, - - */ - @NotNull + /** @deprecated use {@link #sanitizeFileName(String, boolean)} (to be removed in IDEA 17) */ + @SuppressWarnings("unused") public static String sanitizeName(@NotNull String name) { return sanitizeFileName(name, false); } @NotNull - private static String sanitizeFileName(@NotNull String name, boolean strict) { + public static String sanitizeFileName(@NotNull String name, boolean strict) { StringBuilder result = null; + int last = 0; int length = name.length(); for (int i = 0; i < length; i++) { @@ -1238,6 +1236,7 @@ public class FileUtil extends FileUtilRt { if (last < length) { result.append(name, last, length); } + return result.toString(); } @@ -1368,13 +1367,8 @@ public class FileUtil extends FileUtilRt { } File providedFile = new File(providedPath); - if (providedFile.exists()) { - String name = providedFile.getName(); - for (String fileName : fileNames) { - if (name.equals(fileName)) { - return toSystemDependentName(providedFile.getPath()); - } - } + if (providedFile.exists() && ArrayUtil.indexOf(fileNames, providedFile.getName()) >= 0) { + return toSystemDependentName(providedFile.getPath()); } if (providedFile.isDirectory()) { //user chose folder with file @@ -1462,56 +1456,56 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static File createTempDirectory(@NotNull @NonNls String prefix, @Nullable @NonNls String suffix) throws IOException { + public static File createTempDirectory(@NotNull String prefix, @Nullable String suffix) throws IOException { return FileUtilRt.createTempDirectory(prefix, suffix); } @NotNull - public static File createTempDirectory(@NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean deleteOnExit) + public static File createTempDirectory(@NotNull String prefix, @Nullable String suffix, boolean deleteOnExit) throws IOException { return FileUtilRt.createTempDirectory(prefix, suffix, deleteOnExit); } @NotNull - public static File createTempDirectory(@NotNull File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix) + public static File createTempDirectory(@NotNull File dir, @NotNull String prefix, @Nullable String suffix) throws IOException { return FileUtilRt.createTempDirectory(dir, prefix, suffix); } @NotNull public static File createTempDirectory(@NotNull File dir, - @NotNull @NonNls String prefix, - @Nullable @NonNls String suffix, + @NotNull String prefix, + @Nullable String suffix, boolean deleteOnExit) throws IOException { return FileUtilRt.createTempDirectory(dir, prefix, suffix, deleteOnExit); } @NotNull - public static File createTempFile(@NotNull @NonNls String prefix, @Nullable @NonNls String suffix) throws IOException { + public static File createTempFile(@NotNull String prefix, @Nullable String suffix) throws IOException { return FileUtilRt.createTempFile(prefix, suffix); } @NotNull - public static File createTempFile(@NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean deleteOnExit) + public static File createTempFile(@NotNull String prefix, @Nullable String suffix, boolean deleteOnExit) throws IOException { return FileUtilRt.createTempFile(prefix, suffix, deleteOnExit); } @NotNull - public static File createTempFile(@NonNls File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix) throws IOException { + public static File createTempFile(File dir, @NotNull String prefix, @Nullable String suffix) throws IOException { return FileUtilRt.createTempFile(dir, prefix, suffix); } @NotNull - public static File createTempFile(@NonNls File dir, @NotNull @NonNls String prefix, @Nullable @NonNls String suffix, boolean create) + public static File createTempFile(File dir, @NotNull String prefix, @Nullable String suffix, boolean create) throws IOException { return FileUtilRt.createTempFile(dir, prefix, suffix, create); } @NotNull - public static File createTempFile(@NonNls File dir, - @NotNull @NonNls String prefix, - @Nullable @NonNls String suffix, + public static File createTempFile(File dir, + @NotNull String prefix, + @Nullable String suffix, boolean create, boolean deleteOnExit) throws IOException { return FileUtilRt.createTempFile(dir, prefix, suffix, create, deleteOnExit); @@ -1553,16 +1547,16 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static String loadFile(@NotNull File file, @Nullable @NonNls String encoding) throws IOException { + public static String loadFile(@NotNull File file, @Nullable String encoding) throws IOException { return FileUtilRt.loadFile(file, encoding); } @NotNull - public static String loadFile(@NotNull File file, @NotNull @NonNls Charset encoding) throws IOException { + public static String loadFile(@NotNull File file, @NotNull Charset encoding) throws IOException { return String.valueOf(FileUtilRt.loadFileText(file, encoding)); } @NotNull - public static String loadFile(@NotNull File file, @Nullable @NonNls String encoding, boolean convertLineSeparators) throws IOException { + public static String loadFile(@NotNull File file, @Nullable String encoding, boolean convertLineSeparators) throws IOException { return FileUtilRt.loadFile(file, encoding, convertLineSeparators); } @@ -1572,7 +1566,7 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static char[] loadFileText(@NotNull File file, @Nullable @NonNls String encoding) throws IOException { + public static char[] loadFileText(@NotNull File file, @Nullable String encoding) throws IOException { return FileUtilRt.loadFileText(file, encoding); } @@ -1587,7 +1581,7 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static List loadLines(@NotNull File file, @Nullable @NonNls String encoding) throws IOException { + public static List loadLines(@NotNull File file, @Nullable String encoding) throws IOException { return FileUtilRt.loadLines(file, encoding); } @@ -1597,7 +1591,7 @@ public class FileUtil extends FileUtilRt { } @NotNull - public static List loadLines(@NotNull String path, @Nullable @NonNls String encoding) throws IOException { + public static List loadLines(@NotNull String path, @Nullable String encoding) throws IOException { return FileUtilRt.loadLines(path, encoding); } diff --git a/platform/util/src/com/intellij/util/UniqueFileNamesProvider.java b/platform/util/src/com/intellij/util/UniqueFileNamesProvider.java index 08245922bdea..2774661843a2 100644 --- a/platform/util/src/com/intellij/util/UniqueFileNamesProvider.java +++ b/platform/util/src/com/intellij/util/UniqueFileNamesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -33,7 +33,7 @@ public class UniqueFileNamesProvider { } public String suggestName(String originalName) { - String s = FileUtil.sanitizeName(originalName); + String s = FileUtil.sanitizeFileName(originalName, false); if (!contains(s)) { myExistingNames.add(s); return s; @@ -58,7 +58,7 @@ public class UniqueFileNamesProvider { } public static String convertName(String s) { - return FileUtil.sanitizeName(s); + return FileUtil.sanitizeFileName(s, false); } public void reserveFileName(final String fileName) { diff --git a/plugins/settings-repository/src/settings/IcsSettings.kt b/plugins/settings-repository/src/settings/IcsSettings.kt index 082ea5522582..47f127543b5e 100644 --- a/plugins/settings-repository/src/settings/IcsSettings.kt +++ b/plugins/settings-repository/src/settings/IcsSettings.kt @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.jetbrains.settingsRepository import com.fasterxml.jackson.annotation.JsonIgnore @@ -90,7 +105,7 @@ class ReadonlySource(var url: String? = null, var active: Boolean = true) { fileName = fileName.substring(0, fileName.length() - suffix.length()) } // the convention is that the .git extension should be used for bare repositories - return "${FileUtil.sanitizeName(fileName)}.${Integer.toHexString(url!!.hashCode())}.git" + return "${FileUtil.sanitizeFileName(fileName, false)}.${Integer.toHexString(url!!.hashCode())}.git" } } } \ No newline at end of file From 0bf5ad7a76de713b9ac6d18550abd480259bdc68 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 25 Aug 2015 18:58:18 +0300 Subject: [PATCH 06/90] don't show warning message in Quick Doc popup if javadoc was generated from sources (following IDEA-143699) --- .../javadoc/JavaDocInfoGenerator.java | 55 ++++++++++++---- ...JdkClassWhenExternalDocIsNotAvailable.html | 64 +++++++++++++++++++ .../javadoc/JavaDocInfoGeneratorTest.java | 14 +++- 3 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWhenExternalDocIsNotAvailable.html diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index afb99f98519d..9176e09dbc09 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -29,6 +29,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.PackageIndex; +import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; @@ -383,23 +385,52 @@ public class JavaDocInfoGenerator { return null; if (docURLs != null) { - if (buffer.length() == 0) { - buffer.append(""); + if (elementHasSourceCode()) { + LOG.debug("Documentation for " + myElement + " was generated from source code, it wasn't found at following URLs: ", docURLs); + } + else { + if (buffer.length() == 0) { + buffer.append(""); + } + String errorSection = "

Following external urls were checked:
   " + + StringUtil.join(docURLs, new Function() { + @Override + public String fun(String url) { + return XmlStringUtil.escapeString(url); + } + }, "
   ") + + "
The documentation for this element is not found. Please add all the needed paths to API docs in " + + "Project Settings.

"; + buffer.insert(buffer.indexOf(""), errorSection); } - String errorSection = "

Following external urls were checked:
   " + - StringUtil.join(docURLs, new Function() { - @Override - public String fun(String url) { - return XmlStringUtil.escapeString(url); - } - }, "
   ") + - "
The documentation for this element is not found. Please add all the needed paths to API docs in " + - "Project Settings.

"; - buffer.insert(buffer.indexOf(""), errorSection); } return fixupDoc(buffer); } + private boolean elementHasSourceCode() { + VirtualFile[] files; + if (myElement instanceof PsiDirectory) { + final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)myElement); + if (aPackage == null) return false; + files = PackageIndex.getInstance(myProject).getDirectoriesByPackageName(aPackage.getQualifiedName(), true); + } + else if (myElement instanceof PsiPackage) { + files = PackageIndex.getInstance(myProject).getDirectoriesByPackageName(((PsiPackage)myElement).getQualifiedName(), true); + } + else { + PsiFile containingFile = myElement.getNavigationElement().getContainingFile(); + if (containingFile == null) return false; + VirtualFile virtualFile = containingFile.getVirtualFile(); + if (virtualFile == null) return false; + files = new VirtualFile[] {virtualFile}; + } + ProjectFileIndex projectFileIndex = ProjectFileIndex.SERVICE.getInstance(myProject); + for (VirtualFile file : files) { + if (projectFileIndex.isInSource(file)) return true; + } + return false; + } + private void generateClassJavaDoc(@NonNls StringBuilder buffer, PsiClass aClass, boolean generatePrologueAndEpilogue) { if (aClass instanceof PsiAnonymousClass) return; if (generatePrologueAndEpilogue) diff --git a/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWhenExternalDocIsNotAvailable.html b/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWhenExternalDocIsNotAvailable.html new file mode 100644 index 000000000000..f601876a818d --- /dev/null +++ b/java/java-tests/testData/codeInsight/javadocIG/documentationForJdkClassWhenExternalDocIsNotAvailable.html @@ -0,0 +1,64 @@ + java.lang
public final class String
+extends java.lang.Object
+implements java.io.Serializable, java.lang.Comparable<String>, java.lang.CharSequence
+ The String class represents character strings. All + string literals in Java programs, such as "abc", are + implemented as instances of this class. +

+ Strings are constant; their values cannot be changed after they + are created. String buffers support mutable strings. + Because String objects are immutable they can be shared. For example: +

+       String str = "abc";
+   

+ is equivalent to: +

+       char data[] = {'a', 'b', 'c'};
+       String str = new String(data);
+   

+ Here are some more examples of how strings can be used: +

+       System.out.println("abc");
+       String cde = "cde";
+       System.out.println("abc" + cde);
+       String c = "abc".substring(2,3);
+       String d = cde.substring(1, 2);
+   
+

+ The class String includes methods for examining + individual characters of the sequence, for comparing strings, for + searching strings, for extracting substrings, and for creating a + copy of a string with all characters translated to uppercase or to + lowercase. Case mapping is based on the Unicode Standard version + specified by the Character class. +

+ The Java language provides special support for the string + concatenation operator ( + ), and for conversion of + other objects to strings. String concatenation is implemented + through the StringBuilder(or StringBuffer) + class and its append method. + String conversions are implemented through the method + toString, defined by Object and + inherited by all classes in Java. For additional information on + string concatenation and conversion, see Gosling, Joy, and Steele, + The Java Language Specification. + +

Unless otherwise noted, passing a null argument to a constructor + or method in this class will cause a NullPointerException to be + thrown. + +

A String represents a string in the UTF-16 format + in which supplementary characters are represented by surrogate + pairs (see the section Unicode + Character Representations in the Character class for + more information). + Index values refer to char code units, so a supplementary + character uses two positions in a String. +

The String class provides methods for dealing with + Unicode code points (i.e., characters), in addition to those for + dealing with Unicode code units (i.e., char values). + +

Since:
JDK1.0
See Also:
Object.toString(), +StringBuffer, +StringBuilder, +java.nio.charset.Charset
\ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index 6e5f94a36540..e12a8e628eda 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -29,6 +29,8 @@ import com.intellij.testFramework.PsiTestUtil; import java.io.File; import java.io.IOException; +import java.util.Collections; +import java.util.List; /** * @author yole @@ -220,7 +222,11 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { } private void verifyJavaDoc(final PsiElement field) throws IOException { - String docInfo = new JavaDocInfoGenerator(getProject(), field).generateDocInfo(null); + verifyJavaDoc(field, null); + } + + private void verifyJavaDoc(final PsiElement field, List docUrls) throws IOException { + String docInfo = new JavaDocInfoGenerator(getProject(), field).generateDocInfo(docUrls); assertNotNull(docInfo); assertEquals(exampleHtmlFileText(getTestName(true)), replaceEnvironmentDependentContent(docInfo)); } @@ -291,6 +297,12 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { PsiMethod method = psiClass.getMethods()[0]; verifyJavaDoc(method); } + + public void testDocumentationForJdkClassWhenExternalDocIsNotAvailable() throws Exception { + PsiClass aClass = JavaPsiFacade.getInstance(myProject).findClass("java.lang.String", GlobalSearchScope.allScope(myProject)); + assertNotNull(aClass); + verifyJavaDoc(aClass, Collections.singletonList("dummyUrl")); + } @Override protected String getTestDataPath() { From 55df687635abd3e2cf2e0981192cc8f2f46b65e8 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 25 Aug 2015 20:28:53 +0300 Subject: [PATCH 07/90] enable showing javadoc for packages in library sources --- .../javadoc/JavaDocInfoGenerator.java | 5 ++- .../codeInsight/documentation/library-src.jar | Bin 0 -> 1465 bytes .../libraryPackageDocumentation.html | 2 ++ .../JavaExternalDocumentationTest.java | 2 +- .../javadoc/JavaDocInfoGeneratorTest.java | 30 ++++++++++++++++++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/documentation/library-src.jar create mode 100644 java/java-tests/testData/codeInsight/javadocIG/libraryPackageDocumentation.html diff --git a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 9176e09dbc09..2637e6e1e91e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -683,7 +683,10 @@ public class JavaDocInfoGenerator { } private void generatePackageJavaDoc(final StringBuilder buffer, final PsiPackage psiPackage, boolean generatePrologueAndEpilogue) { - for(PsiDirectory directory: psiPackage.getDirectories()) { + VirtualFile[] dirs = PackageIndex.getInstance(myProject).getDirectoriesByPackageName(psiPackage.getQualifiedName(), true); + for (VirtualFile dir : dirs) { + PsiDirectory directory = PsiManager.getInstance(myProject).findDirectory(dir); + if (directory == null) continue; final PsiFile packageInfoFile = directory.findFile(PsiPackage.PACKAGE_INFO_FILE); if (packageInfoFile != null) { final ASTNode node = packageInfoFile.getNode(); diff --git a/java/java-tests/testData/codeInsight/documentation/library-src.jar b/java/java-tests/testData/codeInsight/documentation/library-src.jar new file mode 100644 index 0000000000000000000000000000000000000000..423bc77ce8d71f5c63d685433b383b5bd7a85df1 GIT binary patch literal 1465 zcmWIWW@h1HVBlb2aGEFS&VU417+4sR^K=)PI{D-knrH^ zmjX_vON$iF9Ar_s>eb7~qGPC0CQF@{ef#=&c%*;t{I9Z!>E|3)xrs-4 zcxu`mXMC*q*CnzbVd?VjKS&jc6{r_zJ<5z#T8+w;}*?(@<{{KGq$Cho+ zr<7)`YqR;?IQ5gZ%51SKCsfW<9K82!?XB6h?Q?jKbIF}vz`EaR{RfMAGftFzt$(K} zCw#q&`?|kt=?hJd6*f7~b8d%DUm&!@B`)J*=Yg<`?BRbxRh0hy`+xpS!TWD2SLLto z^33_*6aK*-=gwa}?WOCf<#pzac9@2T&pAII ze^$*a&!0AZ3b-1<40c42lfR|~&UXCLlMt&M*EZP_0C-tV`+I{%TyUv?3pq> z=UwHgFQ=q*O=Qis&yv~r?d;u>{%ZCXGrqGBoB3yL$*f4X z2*YF>nbWJcn}R*Yvwn|37tq-o!5(8|;$q;!nR|gskN_et + Description of com.jetbrains package \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/JavaExternalDocumentationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/JavaExternalDocumentationTest.java index a8e9bad2967f..cacabc9a9cca 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/JavaExternalDocumentationTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/JavaExternalDocumentationTest.java @@ -118,7 +118,7 @@ public class JavaExternalDocumentationTest extends PlatformTestCase { } @NotNull - private static VirtualFile getJarFile(String name) { + public static VirtualFile getJarFile(String name) { VirtualFile file = getVirtualFile(getDataFile(name)); assertNotNull(file); VirtualFile jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(file); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java index e12a8e628eda..606c3b2cc699 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java @@ -17,10 +17,19 @@ package com.intellij.codeInsight.javadoc; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.CodeInsightTestCase; +import com.intellij.codeInsight.JavaExternalDocumentationTest; import com.intellij.lang.java.JavaDocumentationProvider; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; @@ -303,6 +312,27 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase { assertNotNull(aClass); verifyJavaDoc(aClass, Collections.singletonList("dummyUrl")); } + + public void testLibraryPackageDocumentation() throws Exception { + final VirtualFile libClasses = JavaExternalDocumentationTest.getJarFile("library.jar"); + final VirtualFile libSources = JavaExternalDocumentationTest.getJarFile("library-src.jar"); + + ApplicationManager.getApplication().runWriteAction(() -> { + final Library library = LibraryTablesRegistrar.getInstance().getLibraryTable(myProject).createLibrary("myLib"); + final Library.ModifiableModel model = library.getModifiableModel(); + model.addRoot(libClasses, OrderRootType.CLASSES); + model.addRoot(libSources, OrderRootType.SOURCES); + model.commit(); + + Module[] modules = ModuleManager.getInstance(myProject).getModules(); + assertSize(1, modules); + ModuleRootModificationUtil.addDependency(modules[0], library); + }); + + PsiPackage aPackage = JavaPsiFacade.getInstance(myProject).findPackage("com.jetbrains"); + assertNotNull(aPackage); + verifyJavaDoc(aPackage); + } @Override protected String getTestDataPath() { From 762d931633349d85b3aca04969cd5128973917b5 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 25 Aug 2015 20:43:04 +0300 Subject: [PATCH 08/90] delete temp folder if there are no files to keep --- .../src/com/intellij/testFramework/UsefulTestCase.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 399340124fbb..f20ae8f2c842 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -157,13 +157,16 @@ public abstract class UsefulTestCase extends TestCase { FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR); if (hasTmpFilesToKeep()) { File[] files = new File(myTempDir).listFiles(); - if (files != null) { + if (files != null && files.length > 0) { for (File file : files) { if (!shouldKeepTmpFile(file)) { FileUtil.delete(file); } } } + else { + FileUtil.delete(new File(myTempDir)); + } } else { FileUtil.delete(new File(myTempDir)); From d4d7d527c4e602fa133fbebcb4415ded9d6858b5 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 25 Aug 2015 21:28:07 +0300 Subject: [PATCH 09/90] reverted deletion of empty test folders for now --- .../src/com/intellij/testFramework/UsefulTestCase.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index f20ae8f2c842..399340124fbb 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -157,16 +157,13 @@ public abstract class UsefulTestCase extends TestCase { FileUtil.resetCanonicalTempPathCache(ORIGINAL_TEMP_DIR); if (hasTmpFilesToKeep()) { File[] files = new File(myTempDir).listFiles(); - if (files != null && files.length > 0) { + if (files != null) { for (File file : files) { if (!shouldKeepTmpFile(file)) { FileUtil.delete(file); } } } - else { - FileUtil.delete(new File(myTempDir)); - } } else { FileUtil.delete(new File(myTempDir)); From aacd379d4bf9832df8e4817ba6b428eb9a62c31e Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 25 Aug 2015 20:41:29 +0200 Subject: [PATCH 10/90] make IG test light --- .../MalformedFormatString.java | 20 ++--- .../bugs/malformed_format_string/expected.xml | 79 ------------------- .../MalformedFormatStringInspectionTest.java | 19 +++-- 3 files changed, 23 insertions(+), 95 deletions(-) delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java index f494f0190e25..52bad312b971 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java @@ -7,30 +7,30 @@ public class MalformedFormatString { public void foo() { - String.format("%", 3.0); - System.out.printf("%", 3.0); - System.out.printf("%q", 3.0); - System.out.printf("%d", 3.0); - System.out.printf(new Locale(""),"%d%s", 3.0, "foo"); + String.format("%", 3.0); + System.out.printf("%", 3.0); + System.out.printf("%q", 3.0); + System.out.printf("%d", 3.0); + System.out.printf(new Locale(""),"%d%s", 3.0, "foo"); } public static void main(String[] args) { String local = "hmm"; String good = String.format("%s %s", 1, 2); // this is valid according to the inspector (correct) - String warn = String.format("%s %s", 1); // this is invalid according to the inspector (correct) + String warn = String.format("%s %s", 1); // this is invalid according to the inspector (correct) String invalid = String.format("%s %s" + local, 1); // this is valid according to the inspector (INCORRECT!) - String interesting = String.format("%s %s" + "hmm", 1); // this is invalid according to the inspector (correct) + String interesting = String.format("%s %s" + "hmm", 1); // this is invalid according to the inspector (correct) String intAsChar = String.format("symbol '%1$c' (numeric value %1$d)", 60); // integer->char conversion is ok (correct) } public void outOfMemory() { - String.format("%2147483640$s", "s"); + String.format("%2147483640$s", "s"); } public void optionalSettings() { SomeOtherLogger logger = new SomeOtherLogger(); - logger.d("%s %s", 1); // this is invalid according to the inspector (correct) + logger.d("%s %s", 1); // this is invalid according to the inspector (correct) } public class SomeOtherLogger { @@ -40,7 +40,7 @@ public class MalformedFormatString { } void shouldWarn() { - String.format("%1$c %1$d", 10L); + String.format("%1$c %1$d", 10L); } void shouldNotWarn() { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml deleted file mode 100644 index 8363c90a165c..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/expected.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - MalformedFormatString.java - 10 - Malformed format string - Too many arguments for format string "%" #loc - - - - MalformedFormatString.java - 11 - Malformed format string - Too many arguments for format string "%" #loc - - - - MalformedFormatString.java - 12 - Malformed format string - Format string "%q" is malformed #loc - - - - MalformedFormatString.java - 13 - Malformed format string - Format string "%d" does not match the type of its arguments #loc - - - - MalformedFormatString.java - 14 - Malformed format string - Format string "%d%s" does not match the type of its arguments #loc - - - - MalformedFormatString.java - 21 - Malformed format string - Too few arguments for format string "%s %s" #loc - - - - - - MalformedFormatString.java - 23 - Malformed format string - Too few arguments for format string "%s %s" + "hmm" #loc - - - - MalformedFormatString.java - 28 - Malformed format string - Too few arguments for format string "%2147483640$s" #loc - - - - MalformedFormatString.java - 33 - Malformed format string - Too few arguments for format string "%s %s" #loc - - - - MalformedFormatString.java - 43 - Malformed format string - Format string <code>"%1$c %1$d"</code> does not match the type of its arguments #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java index 6d0149c9d8f1..c3ea5da0f6b4 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/MalformedFormatStringInspectionTest.java @@ -1,14 +1,21 @@ package com.siyeh.ig.bugs; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.Nullable; -public class MalformedFormatStringInspectionTest extends IGInspectionTestCase { +public class MalformedFormatStringInspectionTest extends LightInspectionTestCase { - public void test() throws Exception { - MalformedFormatStringInspection inspection = new MalformedFormatStringInspection(); + public void testMalformedFormatString() { + doTest(); + } + + @Nullable + @Override + protected InspectionProfileEntry getInspection() { + final MalformedFormatStringInspection inspection = new MalformedFormatStringInspection(); inspection.classNames.add("com.siyeh.igtest.bugs.malformed_format_string.MalformedFormatString.SomeOtherLogger"); inspection.methodNames.add("d"); - - doTest("com/siyeh/igtest/bugs/malformed_format_string", inspection); + return inspection; } } \ No newline at end of file From 198485cf29b4a705a2109cfa412a234589a25598 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 25 Aug 2015 20:57:04 +0200 Subject: [PATCH 11/90] IDEA-143355 (String.format() with java.sql.Timestamp) --- .../src/com/siyeh/ig/bugs/FormatDecode.java | 8 ++++---- .../malformed_format_string/MalformedFormatString.java | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/FormatDecode.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/FormatDecode.java index f09496b9a3e7..9c027f4e96a7 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/FormatDecode.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/FormatDecode.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package com.siyeh.ig.bugs; import com.intellij.psi.CommonClassNames; import com.intellij.psi.PsiType; +import com.intellij.psi.util.InheritanceUtil; import java.util.ArrayList; import java.util.HashSet; @@ -151,11 +152,10 @@ class FormatDecode { @Override public boolean valid(PsiType type) { final String text = type.getCanonicalText(); - return PsiType.LONG.equals(type) || CommonClassNames.JAVA_LANG_LONG.equals(text) || - CommonClassNames.JAVA_UTIL_DATE.equals(text) || - CommonClassNames.JAVA_UTIL_CALENDAR.equals(text); + InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_DATE) || + InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_CALENDAR); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java index 52bad312b971..0302496818f9 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/malformed_format_string/MalformedFormatString.java @@ -1,7 +1,7 @@ package com.siyeh.igtest.bugs.malformed_format_string; import java.util.Locale; - +import java.sql.Timestamp; public class MalformedFormatString { @@ -47,4 +47,8 @@ public class MalformedFormatString { String.format("%c", 0x10300); String charAsInt = String.format("%1$d %1$c", 10); // int followed by char should be ok too. } + + String timestamp(Timestamp ts) { + return String.format("%tF %tT", ts, ts); + } } From 1f32e521f48655a1d7edaabe513548a43b499d70 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 25 Aug 2015 20:57:11 +0200 Subject: [PATCH 12/90] remove unused PsiFormatUtil.getRawExternalName --- .../com/intellij/psi/util/PsiFormatUtil.java | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java index feccd0171c95..a5a913bf8093 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiFormatUtil.java @@ -452,40 +452,6 @@ public class PsiFormatUtil extends PsiFormatUtilBase { return builder.toString(); } - @Nullable - public static String getRawExternalName(PsiModifierListOwner owner) { - final StringBuilder builder = new StringBuilder(); - final PsiClass psiClass = PsiTreeUtil.getParentOfType(owner, PsiClass.class, false); - if (psiClass == null) return null; - ClassUtil.formatClassName(psiClass, builder); - if (owner instanceof PsiMethod) { - builder.append(" "); - formatMethod((PsiMethod)owner, PsiSubstitutor.EMPTY, - SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_RAW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES, - SHOW_TYPE | SHOW_RAW_TYPE | SHOW_FQ_CLASS_NAMES, - Integer.MAX_VALUE, builder); - } - else if (owner instanceof PsiParameter) { - final PsiElement declarationScope = ((PsiParameter)owner).getDeclarationScope(); - if (!(declarationScope instanceof PsiMethod)) { - return null; - } - final PsiMethod psiMethod = (PsiMethod)declarationScope; - - builder.append(" "); - formatMethod(psiMethod, PsiSubstitutor.EMPTY, - SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_RAW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES, - SHOW_TYPE | SHOW_RAW_TYPE | SHOW_FQ_CLASS_NAMES, - Integer.MAX_VALUE, builder); - builder.append(" "); - builder.append(psiMethod.getParameterList().getParameterIndex((PsiParameter)owner)); - } - else { - return null; - } - return builder.toString(); - } - public static String getPackageDisplayName(@NotNull final PsiClass psiClass) { if (psiClass instanceof PsiTypeParameter) { PsiTypeParameterListOwner owner = ((PsiTypeParameter)psiClass).getOwner(); From c3bf675eab1dc89884d8cbfde3788b8d0b57504a Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 25 Aug 2015 21:14:34 +0200 Subject: [PATCH 13/90] don't mention LookupItem in EmptyLookupItem --- .../lookup/impl/EmptyLookupItem.java | 20 ++++++++++++++++--- .../codeInsight/lookup/impl/LookupImpl.java | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EmptyLookupItem.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EmptyLookupItem.java index ce8c913b1b99..c186a2ee66ab 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EmptyLookupItem.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EmptyLookupItem.java @@ -15,19 +15,33 @@ */ package com.intellij.codeInsight.lookup.impl; -import com.intellij.codeInsight.lookup.LookupItem; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementPresentation; +import org.jetbrains.annotations.NotNull; /** * @author peter */ -public class EmptyLookupItem extends LookupItem { +public class EmptyLookupItem extends LookupElement { + private final String myText; private final boolean myLoading; public EmptyLookupItem(final String s, boolean loading) { - super(s, " "); + myText = s; myLoading = loading; } + @NotNull + @Override + public String getLookupString() { + return " "; + } + + @Override + public void renderElement(LookupElementPresentation presentation) { + presentation.setItemText(myText); + } + public boolean isLoading() { return myLoading; } 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 84ed80e0c3ea..93e44e5be1d1 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 @@ -424,7 +424,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, } private void addEmptyItem(CollectionListModel model) { - LookupItem item = new EmptyLookupItem(myCalculating ? " " : LangBundle.message("completion.no.suggestions"), false); + LookupElement item = new EmptyLookupItem(myCalculating ? " " : LangBundle.message("completion.no.suggestions"), false); myMatchers.put(item, new CamelHumpMatcher("")); model.add(item); From b429d869c8e9a77949bf6f9233eeb4a2e8096070 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 25 Aug 2015 21:22:51 +0200 Subject: [PATCH 14/90] let VariableLookupItem render itself --- .../lookup/VariableLookupItem.java | 19 ++++++++++++-- .../impl/JavaElementLookupRenderer.java | 26 ++----------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java index 8eea1dd64231..ab7420175c92 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/VariableLookupItem.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.daemon.impl.JavaColorProvider; import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil; +import com.intellij.codeInsight.lookup.impl.JavaElementLookupRenderer; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; @@ -92,6 +93,7 @@ public class VariableLookupItem extends LookupItem implements Typed } @Override + @NotNull public PsiType getType() { return getSubstitutor().substitute(getObject().getType()); } @@ -124,12 +126,25 @@ public class VariableLookupItem extends LookupItem implements Typed @Override public void renderElement(LookupElementPresentation presentation) { - super.renderElement(presentation); + boolean qualify = getAttribute(FORCE_QUALIFY) != null; + + PsiVariable variable = getObject(); + String name = variable.getName(); + if (qualify && variable instanceof PsiField && ((PsiField)variable).getContainingClass() != null) { + name = ((PsiField)variable).getContainingClass().getName() + "." + name; + } + presentation.setItemText(name); + + presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(this, presentation.isReal())); + presentation.setStrikeout(JavaElementLookupRenderer.isToStrikeout(this)); + if (myHelper != null) { - myHelper.renderElement(presentation, getAttribute(FORCE_QUALIFY) != null ? Boolean.TRUE : null, getSubstitutor()); + myHelper.renderElement(presentation, qualify ? Boolean.TRUE : null, getSubstitutor()); } if (myColor != null) { presentation.setTypeText("", new ColorIcon(12, myColor)); + } else { + presentation.setTypeText(getType().getPresentableText()); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/impl/JavaElementLookupRenderer.java b/java/java-impl/src/com/intellij/codeInsight/lookup/impl/JavaElementLookupRenderer.java index bf64fce02a79..e30d5d0043a0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/impl/JavaElementLookupRenderer.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/impl/JavaElementLookupRenderer.java @@ -19,7 +19,6 @@ import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.lookup.LookupItem; -import com.intellij.codeInsight.lookup.VariableLookupItem; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.beanProperties.BeanPropertyElement; @@ -34,8 +33,7 @@ import java.util.List; public class JavaElementLookupRenderer implements ElementLookupRenderer { @Override public boolean handlesItem(final Object element) { - return element instanceof PsiVariable || - element instanceof PsiKeyword || element instanceof PsiExpression || + return element instanceof PsiKeyword || element instanceof PsiExpression || element instanceof PsiTypeElement || element instanceof BeanPropertyElement; } @@ -69,18 +67,6 @@ public class JavaElementLookupRenderer implements ElementLookupRenderer { } } } - else if (o instanceof PsiArrayType) { - name = ((PsiArrayType)o).getDeepComponentType().getPresentableText(); - } - else if (o instanceof PsiType) { - name = ((PsiType)o).getPresentableText(); - } - - if (item.getAttribute(LookupItem.FORCE_QUALIFY) != null) { - if (o instanceof PsiMember && ((PsiMember)o).getContainingClass() != null) { - name = ((PsiMember)o).getContainingClass().getName() + "." + name; - } - } return StringUtil.notNullize(name); } @@ -91,15 +77,7 @@ public class JavaElementLookupRenderer implements ElementLookupRenderer { if (o instanceof PsiElement) { final PsiElement element = (PsiElement)o; if (element.isValid()) { - if (element instanceof PsiVariable){ - PsiVariable variable = (PsiVariable)element; - PsiType type = variable.getType(); - if (item instanceof VariableLookupItem) { - type = ((VariableLookupItem)item).getSubstitutor().substitute(type); - } - text = type.getPresentableText(); - } - else if (element instanceof PsiExpression){ + if (element instanceof PsiExpression){ PsiExpression expression = (PsiExpression)element; PsiType type = expression.getType(); if (type != null){ From c89b9ff1b292ecf5b226699df87cfea451111f19 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 25 Aug 2015 21:36:39 +0200 Subject: [PATCH 15/90] don't overburden java/js insert handlers with live templates --- .../completion/DefaultInsertHandler.java | 19 ++++--------------- .../SmartCompletionTemplateItem.java | 17 ++++++----------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java index c3472a58937f..39a74f7a5e29 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/DefaultInsertHandler.java @@ -26,11 +26,9 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -import org.jetbrains.annotations.NotNull; -public class DefaultInsertHandler extends TemplateInsertHandler implements Cloneable { +public class DefaultInsertHandler implements InsertHandler { public static final DefaultInsertHandler NO_TAIL_HANDLER = new DefaultInsertHandler(){ @Override @@ -40,13 +38,9 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone }; @Override - public void handleInsert(final InsertionContext context, LookupElement item) { - super.handleInsert(context, item); - - handleInsertInner(context, (LookupItem)item, context.getCompletionChar()); - } - - private void handleInsertInner(InsertionContext context, LookupItem item, final char completionChar) { + public void handleInsert(final InsertionContext context, LookupElement lookupElement) { + LookupItem item = (LookupItem)lookupElement; + char completionChar = context.getCompletionChar(); final Project project = context.getProject(); final Editor editor = context.getEditor(); final Document document = editor.getDocument(); @@ -170,11 +164,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone return editor.getCaretModel().getOffset(); } - @Override - protected void populateInsertMap(@NotNull final PsiFile file, @NotNull final OffsetMap offsetMap) { - JavaCompletionUtil.initOffsets(file, offsetMap); - } - public static class InsertHandlerState{ int tailOffset; int caretOffset; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionTemplateItem.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionTemplateItem.java index 3936b22bf89d..fd5cd78f3b8d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionTemplateItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionTemplateItem.java @@ -1,32 +1,29 @@ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.codeInsight.lookup.TypedLookupItem; import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.impl.LiveTemplateLookupElementImpl; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiType; import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NonNls; /** * @author peter */ -public class SmartCompletionTemplateItem extends LookupItem