Index: trunk/src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 6555)
+++ trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 6556)
@@ -8,4 +8,11 @@
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
 import org.openstreetmap.josm.data.projection.Projections;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.openstreetmap.josm.tools.Predicate;
+import org.openstreetmap.josm.tools.Utils;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
@@ -337,3 +344,35 @@
         return false;
     }
+
+    /**
+     * Tests whether {@code this} node is connected to {@code otherNode} via at most {@code hops} nodes
+     * matching the {@code predicate} (which may be {@code null} to consider all nodes).
+     */
+    public boolean isConnectedTo(final Collection<Node> otherNodes, final int hops, Predicate<Node> predicate) {
+        CheckParameterUtil.ensureParameterNotNull(otherNodes);
+        CheckParameterUtil.ensureThat(!otherNodes.isEmpty(), "otherNodes must not be empty!");
+        CheckParameterUtil.ensureThat(hops >= 0, "hops must be non-negative!");
+        return hops == 0
+                ? isConnectedTo(otherNodes, hops, predicate, null)
+                : isConnectedTo(otherNodes, hops, predicate, new TreeSet<Node>());
+    }
+
+    private boolean isConnectedTo(final Collection<Node> otherNodes, final int hops, Predicate<Node> predicate, Set<Node> visited) {
+        if (otherNodes.contains(this)) {
+            return true;
+        }
+        if (hops > 0) {
+            visited.add(this);
+            for (final Way w : Utils.filteredCollection(this.getReferrers(), Way.class)) {
+                for (final Node n : w.getNodes()) {
+                    final boolean containsN = visited.contains(n);
+                    visited.add(n);
+                    if (!containsN && (predicate == null || predicate.evaluate(n)) && n.isConnectedTo(otherNodes, hops - 1, predicate, visited)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java	(revision 6555)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/UnconnectedWays.java	(revision 6556)
@@ -114,5 +114,5 @@
         mindist = Main.pref.getDouble(PREFIX + ".node_way_distance", 10.0);
         minmiddledist = Main.pref.getDouble(PREFIX + ".way_way_distance", 0.0);
-        dsArea = Main.main.getCurrentDataSet().getDataSourceArea();
+        dsArea = Main.main == null || !Main.main.hasEditLayer() ? null : Main.main.getCurrentDataSet().getDataSourceArea();
     }
 
@@ -135,9 +135,8 @@
                         continue;
                     }
-                    // There's a small false-positive here.  Imagine an intersection
-                    // like a 't'.  If the top part of the 't' is short enough, it
-                    // will trigger the node at the very top of the 't' to be unconnected
-                    // to the way that "crosses" the 't'.  We should probably check that
-                    // the ways to which 'en' belongs are not connected to 's.w'.
+                    // to handle intersections of 't' shapes and similar
+                    if (en.isConnectedTo(s.w.getNodes(), 3 /* hops */, null)) {
+                        continue;
+                    }
                     map.put(en, s.w);
                 }
